100 Statistical Tests in R Notebook

This is the R Notebook for the Book 100 Statistical Tests in R from (Lewis, Lewis, and Lewis 2013).

In order to better illustrate the statistical tests through real-world applications, this notebook will use the built-in R datasets to cover all test types. Run the following codes to ensure all packages and datasets are prepared.

library(psych)
# Load core datasets
data(iris)
data(mtcars)
data(airquality)
data(sleep)
data(UCBAdmissions)
data(faithful)
data(AirPassengers)

# For survival analysis
library(lattice)
library(survival)
data(lung)

# For circular statistics
library(circular)
data(wind)

# For visualisation
library(ggplot2)
library(tidyverse)

Test 1 Pearson’s product moment correlation coefficient T-test

To assess the null hypothesis of zero correlation between two variables. When to use this test?

  • Interval or ratio scale

  • No need for same scale

  • A paired sample with approximately normally distributed

  • Joint distribution is bivariate normal

  • Linear relationships

In this test, we will use iris dataset to compare and illustrate the relationship between lengths of sepals and petals.

str(iris)
'data.frame':   150 obs. of  5 variables:
 $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
 $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
 $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
 $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
 $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
summary(iris)
  Sepal.Length    Sepal.Width     Petal.Length    Petal.Width   
 Min.   :4.300   Min.   :2.000   Min.   :1.000   Min.   :0.100  
 1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.300  
 Median :5.800   Median :3.000   Median :4.350   Median :1.300  
 Mean   :5.843   Mean   :3.057   Mean   :3.758   Mean   :1.199  
 3rd Qu.:6.400   3rd Qu.:3.300   3rd Qu.:5.100   3rd Qu.:1.800  
 Max.   :7.900   Max.   :4.400   Max.   :6.900   Max.   :2.500  
       Species  
 setosa    :50  
 versicolor:50  
 virginica :50  
                
                
                
summary(iris$Sepal.Length)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  4.300   5.100   5.800   5.843   6.400   7.900 
summary(iris$Petal.Length)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   1.600   4.350   3.758   5.100   6.900 
cor.test(iris$Sepal.Length,iris$Petal.Length, method = "pearson", alterantive = "two.sided", conf.level = 0.95)

    Pearson's product-moment correlation

data:  iris$Sepal.Length and iris$Petal.Length
t = 21.646, df = 148, p-value < 2.2e-16
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.8270363 0.9055080
sample estimates:
      cor 
0.8717538 

The correlation between x (length of sepals) and y (length of petal) is 0.872. The p-value is smaller than 0.05, we reject the null hypothesis of zero correlation. 95% confidence interval is reported betwewn [0.827,0.906], which does not cross zero.

plot(iris$Sepal.Length,iris$Petal.Length)


cor_test_iris_Sepal_Petal_length <- ggplot(data = iris, aes(x=Sepal.Length, y=Petal.Length)) + 
  geom_point()

cor_test_iris_Sepal_Petal_length

Test 2 Spearman Rank Correlation Test

When to use this test?

  • To assess the null hypothesis of zero correlation between two variables.

  • Ordinal or ranked data

  • Data is continuous and unreasonable to assume the variables are normally distributed

  • Linear relationship

In this test, we will continue to use iris dataset to compare and illustrate the relationship between lengths of sepals and petals.

cor.test(iris$Sepal.Length,iris$Petal.Length, method = "spearman", alternative = "two.sided")

    Spearman's rank correlation rho

data:  iris$Sepal.Length and iris$Petal.Length
S = 66429, p-value < 2.2e-16
alternative hypothesis: true rho is not equal to 0
sample estimates:
      rho 
0.8818981 

The correlation between x (length of sepals) and y (length of petal) is 0.882. The p-value is smaller than 0.05, we reject the null hypothesis of zero correlation. In the spearman test, there is no confidence interval normally. Spearman correlation uses rank-based calculations rather than the raw data values, making the sampling distribution more complex for computing confidence intervals using standard parametrix methods.

Test 3 Kendall’s Tau Correlation Coefficient Test

When to use this test?

  • a paired random sample of ordinal or ranked data

  • data is continuous and it is unreasonable to the variables are normally distributed

  • linear relationship

We will use a new dataset mtcars to illustrate the Tau correlation coefficient test:

[, 1] mpg Miles/(US) gallon
[, 2] cyl Number of cylinders
[, 3] disp Displacement (cu.in.)
[, 4] hp Gross horsepower
[, 5] drat Rear axle ratio
[, 6] wt Weight (1000 lbs)
[, 7] qsec 1/4 mile time
[, 8] vs Engine (0 = V-shaped, 1 = straight)
[, 9] am Transmission (0 = automatic, 1 = manual)
[,10] gear Number of forward gears
str(mtcars)
'data.frame':   32 obs. of  11 variables:
 $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
 $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
 $ disp: num  160 160 108 258 360 ...
 $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
 $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
 $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
 $ qsec: num  16.5 17 18.6 19.4 17 ...
 $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
 $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
 $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
 $ carb: num  4 4 1 1 2 1 4 2 2 4 ...
summary(mtcars)
      mpg             cyl             disp             hp       
 Min.   :10.40   Min.   :4.000   Min.   : 71.1   Min.   : 52.0  
 1st Qu.:15.43   1st Qu.:4.000   1st Qu.:120.8   1st Qu.: 96.5  
 Median :19.20   Median :6.000   Median :196.3   Median :123.0  
 Mean   :20.09   Mean   :6.188   Mean   :230.7   Mean   :146.7  
 3rd Qu.:22.80   3rd Qu.:8.000   3rd Qu.:326.0   3rd Qu.:180.0  
 Max.   :33.90   Max.   :8.000   Max.   :472.0   Max.   :335.0  
      drat             wt             qsec             vs        
 Min.   :2.760   Min.   :1.513   Min.   :14.50   Min.   :0.0000  
 1st Qu.:3.080   1st Qu.:2.581   1st Qu.:16.89   1st Qu.:0.0000  
 Median :3.695   Median :3.325   Median :17.71   Median :0.0000  
 Mean   :3.597   Mean   :3.217   Mean   :17.85   Mean   :0.4375  
 3rd Qu.:3.920   3rd Qu.:3.610   3rd Qu.:18.90   3rd Qu.:1.0000  
 Max.   :4.930   Max.   :5.424   Max.   :22.90   Max.   :1.0000  
       am              gear            carb      
 Min.   :0.0000   Min.   :3.000   Min.   :1.000  
 1st Qu.:0.0000   1st Qu.:3.000   1st Qu.:2.000  
 Median :0.0000   Median :4.000   Median :2.000  
 Mean   :0.4062   Mean   :3.688   Mean   :2.812  
 3rd Qu.:1.0000   3rd Qu.:4.000   3rd Qu.:4.000  
 Max.   :1.0000   Max.   :5.000   Max.   :8.000  
cor.test(mtcars$hp,mtcars$wt, method="kendal", alternative = "two.sided")

    Kendall's rank correlation tau

data:  mtcars$hp and mtcars$wt
z = 4.845, p-value = 1.266e-06
alternative hypothesis: true tau is not equal to 0
sample estimates:
      tau 
0.6113081 

The correlation between x (hp) and y (wt) is 0.611. The p-value is significant smaller than the critical value 0.05. Therefore, we reject the null hypothesis.

Test 4 Z-Test of the Difference Between Independent Correlations

When to use this test?

  • correlation coefficients calculated from independent samples

  • data are assumed to be bivariate normal

  • sample size may be different

Z-test is less common than Pearson or Spearman correlation. It actually examines whether the correlation coefficients from two or more samples with different sample size is correlated or not.

In this test, we will use iris dataset as the example. We will first calculate the correlation coefficients of Sepal length and Petal length from different species. After that, we will examine the Z-test between these correlation coefficients. We also need ‘psych’ package to use paried.r function. This function require six parameters: correlation coefficients xy, correlation coeefficients xz, correlaiton yz = NULL, number in first group, number in second group, twotailed

cor_setosa <- cor(iris$Sepal.Length[iris$Species == "setosa"], iris$Petal.Length[iris$Species == "setosa"], method = "pearson")
cor_versicolor <- cor(iris$Sepal.Width[iris$Species == "versicolor"], iris$Petal.Width[iris$Species == "versicolor"], method = "pearson")
n_setosa <- sum(iris$Species == "setosa")
n_versicolor <- sum(iris$Species == "versicolor")

Now we will use paired.r() to calculate the Z-test.

z_test_cor_setosa_versicolor <- paired.r(cor_setosa, cor_versicolor, NULL, n_setosa, n_versicolor, twotailed=TRUE)
z_test_cor_setosa_versicolor$test
[1] "test of difference between two independent correlations"
z_test_cor_setosa_versicolor$z
[1] 2.550422
z_test_cor_setosa_versicolor$p
[1] 0.01075925

The p-value is less than the critical value 0.05. Therefore we can reject the null hypothesis.

Test 5 Difference Between Two Overlapping Correlation Coefficients

When to use this test?

  • Compare the null hypothesis of zero correlation between one pair of variables and another pair of variables shared with an overlapping variable

  • aim to select the better indicator of two available predictors (x and y) for a dependent variable z

  • data are assumed to be normally distributed

  • referred to as Steiger’s t-test, Meng’s t-test, Rosenthal & Rubin’s t-test or Williams test

We will use mtcars to evaluate the relationships between the correlation of wt (weights) and mpg (miles per gallon) and the correlation of hp (horsepower) and mpg and figure out whether wt or hp is a better indicator of mpg.

We will need compOverlapCorr and psych packages for this test.

library(compOverlapCorr)
library(psych)
cor_mpg_wt <- cor(mtcars$mpg,mtcars$wt, method = "pearson")
cor_mpg_hp <- cor(mtcars$mpg, mtcars$hp, method = "pearson")
cor_hp_wt <- cor(mtcars$hp, mtcars$wt, method = "pearson")
compOverlapCorr(length(mtcars$mpg), cor_mpg_wt, cor_mpg_hp, cor_hp_wt)
[1] -1.3303850  0.1833915

The first number is the result of t-test and the second number is p-value. The p-value is greater than the critical value 0.05. Therefore, we can not reject the null hypothesis.

We can also use psych package to calculate this correlation.

paired.r(cor_mpg_wt, cor_mpg_hp, cor_hp_wt, length(mtcars$mpg), twotailed = TRUE)
Call: paired.r(xy = cor_mpg_wt, xz = cor_mpg_hp, yz = cor_hp_wt, n = length(mtcars$mpg), 
    twotailed = TRUE)
[1] "test of difference between two correlated  correlations"
t = -1.35  With probability =  0.19

We can see the same results from both two packages. As the package {compOverlapCorr} is no longer maintained, we should use {psych} to measure this test.

Test 6 Difference Between Two Non-Overlapping Dependent Correlation Coefficients

Question to the test addresses:

Is the correlation between two variables (A and B) significantly different from the correlation between two other variables (C and D), when all four variables were measured in the same group.

When to use this test?

  • To assess the difference between one pair of variables and a second non-overlapping pair of variables.

  • Non-overlapping could be related items in different times

  • Data are assumed to be normally distributed

Usually, this method aims to discuss the difference in correlation between two variables in two different times for serial analysis. Here, we will discuss the basic mode of this test, two independent sets of variables in the dataset mtcars.

For the cars in this dataset, is the relationship between engine power (hp and disp) significantly different with the relationship between performance (mpg and wt)

library("psych")
cor_hp_disp <- cor(mtcars$hp, mtcars$disp, method = "pearson")
cor_mpg_wt <- cor(mtcars$mpg, mtcars$wt, method ="pearson")
#we also need the cross relationships between these variables

cor_hp_wt <- cor(mtcars$hp, mtcars$wt, method = "pearson")
cor_mpg_disp <- cor(mtcars$mpg, mtcars$disp, method = "pearson")
cor_mpg_hp <- cor(mtcars$mpg, mtcars$hp, method = "pearson")
cor_disp_wt <- cor(mtcars$disp, mtcars$wt, method = "pearson")
r.test(length(mtcars$mpg), r12 = cor_hp_wt,r34 =  cor_mpg_wt,r23 = cor_mpg_disp, r13 = cor_hp_wt, r14 = cor_hp_wt, r24 = cor_mpg_disp, twotailed = TRUE)
Correlation tests 
Call:r.test(n = length(mtcars$mpg), r12 = cor_hp_wt, r34 = cor_mpg_wt, 
    r23 = cor_mpg_disp, r13 = cor_hp_wt, r14 = cor_hp_wt, r24 = cor_mpg_disp, 
    twotailed = TRUE)
Test of difference between two dependent correlations 
 z value 5.52    with probability  0

We can see the p-value is 0, smaller than the critical value 0.05. Therefore, we can reject the null hypothesis. The correlation between engine powers and correlation between power performance are different.

Test 7 Bartlett’s Test of Sphericity

Question to the test addresses:

Are these variables essentially independent of each other?

When to use this test?

  • check the correlation matrix is different from identity matrix

  • identity matrix means all variables in this matrix are uncorrelated

  • to check whether data is suitable for factor analysis (FA)

For researcher, if we want to conduct factor analysis for our variables, it is important that we should reject the null hypothesis of Bartlett’s test that there is no difference between our variable matrix and identity matrix. Only when variables are correlated with each other, we can continue to do factor analysis.

For this test, we will use iris dataset to test the variable matrix among Sepal.Length, Sepal.Width, Petal.Length, Petal.Width.

library("psych")
matrix_data <- iris[, 1:4]
cortest.bartlett(matrix_data)
$chisq
[1] 706.9592

$p.value
[1] 1.92268e-149

$df
[1] 6

According to the result, we can find the p-value is smaller than the critical value 0.05. Therefore, we should reject the null hypothesis that our matrix is the identity matrix. We can argue that there are internal correlations between our matrix among Sepal.Length, Sepal,Width, Petal.Length, and Petal.Width.

Test 8 The Jennrich Test of the Equality of Two Matrices

Question to the test addresses:

Is the fundamental pattern of correlations at A the same as the pattern at B?

To use this test:

  • Two independent samples or subsamples

  • The same set of variables measured for both groups

  • The data are assumed to be normally distributed

In this test, we will use the EuStockMarkets dataset, which is a built-in dataset in R, measuring the daily closing prices for 4 major EU stock indices from 1991-1998.

We will examine the correlation pattern between the DAX, SMI, CAC, and FTSE indices different in the first half of the time period and the second half of the time period.

library("psych")
sample1 <- EuStockMarkets[1:900, ]
sample2 <- EuStockMarkets[961:1860, ]
cortest.jennrich(sample1,sample2)
$chi2
[1] -719.9148

$prob
[1] 1

According to the result, we can find the p-value is larger than the critical value 0.05. Therefore, we can not reject the null hypothesis that the correlation patterns of these two samples are statistically the same. The overall pattern of correlation between the major EU stock indices did not significantly change between the two time periods.

Test 9 The Granger Causality Test

Question to the test addresses:

Is one time series useful in forecasting another time series?

To use this test:

  • at least two time series data

  • stationary data: all properties of data are constant over time such as mean, variance and autocorrelation

  • data are assumed to be ordered chronologically

In this test, we will continue to use the time series data EuStockMarters with the diff() function to create a suitable dataset for this analysis. We will test these relationships:

  • Dose DAX Granger-cause CAC?

  • Does DAX Granger-cause FTSE?

  • Does SMI Granger-cause CAC?

  • Does SMI Granger-cause FTSE?

data("EuStockMarkets")
dax_diff <- diff(EuStockMarkets[,"DAX"])
smi_diff <- diff(EuStockMarkets[,"SMI"])
cac_diff <- diff(EuStockMarkets[,"CAC"])
ftse_diff <- diff(EuStockMarkets[,"FTSE"])
library(lmtest)
grangertest(cac_diff ~ dax_diff, order = 3)
Granger causality test

Model 1: cac_diff ~ Lags(cac_diff, 1:3) + Lags(dax_diff, 1:3)
Model 2: cac_diff ~ Lags(cac_diff, 1:3)
  Res.Df Df      F Pr(>F)
1   1849                 
2   1852 -3 0.8165 0.4847

According to the result, we can find that the p-value is larger than the critical value 0.05.Therefore, we can not reject the null hypothesis that DAX does not Granger-cause CAC. Similarly, we can continue to finish the rest of tests

grangertest(ftse_diff ~ dax_diff, order = 3)
Granger causality test

Model 1: ftse_diff ~ Lags(ftse_diff, 1:3) + Lags(dax_diff, 1:3)
Model 2: ftse_diff ~ Lags(ftse_diff, 1:3)
  Res.Df Df      F Pr(>F)
1   1849                 
2   1852 -3 1.3093 0.2697
grangertest(cac_diff ~ smi_diff, order = 3)
Granger causality test

Model 1: cac_diff ~ Lags(cac_diff, 1:3) + Lags(smi_diff, 1:3)
Model 2: cac_diff ~ Lags(cac_diff, 1:3)
  Res.Df Df      F   Pr(>F)   
1   1849                      
2   1852 -3 3.9466 0.008081 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
grangertest(ftse_diff ~ smi_diff, order = 3)
Granger causality test

Model 1: ftse_diff ~ Lags(ftse_diff, 1:3) + Lags(smi_diff, 1:3)
Model 2: ftse_diff ~ Lags(ftse_diff, 1:3)
  Res.Df Df      F    Pr(>F)    
1   1849                        
2   1852 -3 5.5971 0.0008069 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

According to the test, we can see that the latter two p-values are significant smaller than the critical value 0.05. Therefore, we can reject the null hypothesises. SMI Granger-causes the FTSE and CAC.

We can also visualise these results to “see” the relationships. We will use ggplot 2 and zoo packages.

library(ggplot2)
library(zoo)

plot_data <- data.frame(
  Date = 1:length(dax_diff),
  SMI = as.numeric(smi_diff),
  CAC = as.numeric(cac_diff),
  FTSE = as.numeric(ftse_diff)
)

ggplot(plot_data, aes(x=Date)) +
  geom_line(aes(y=SMI, color = "SMI")) +
  geom_line(aes(y=CAC, color="CAC")) +
  labs(title = "Daily Changes in SMI and CAC", y = "Changes in Price", x="Changes in Day") +
  theme_minimal()


ggplot(plot_data, aes(x=Date)) +
  geom_line(aes(y=SMI, color = "SMI")) +
  geom_line(aes(y=FTSE, color="FTSE")) +
  labs(title = "Daily Changes in SMI and FTSE", y = "Changes in Price", x="Changes in Day") +
  theme_minimal()

Test 10 Durbin-Watson Autocorrelation Test

Question to the test addresses:

Is there serial correlation in the sample?

To use this test:

  • whether residuals (error terms) from a regression model are independent

  • residuals are stationary and normally distribution with zero mean

If residuals are not independent, the model will have incorrect standard errors, misleading p-values and false positives. The error from one observation provides information about the error in the next observation, which violates the assumption of linear regression.

For this test, we will use cars to build a simple linear regression model, and test the relationship between dist ~ speed.

data("cars")

car_model <- lm(dist ~ speed, data = cars)
library("car")
durbinWatsonTest(car_model)
 lag Autocorrelation D-W Statistic p-value
   1       0.1604322      1.676225   0.194
 Alternative hypothesis: rho != 0

According to the result, we can see that the p-value is larger than the critical value 0.05. Therefore, we can not reject the null hypothesis that there is no autocorrelations in this model.

To visualise the residuals, we can plot each residual against the one that came before it (the lagged value). If there is no autocorrelation, we should see the random dot cloud with no observable pattern.

res <- residuals(car_model)

residual_data <- data_frame(
  Residuals = res[-1],
  Lagged_Residuals = res[-length(res)]
)

ggplot(residual_data, aes(x = Lagged_Residuals, y= Residuals)) +
  geom_point() +
  geom_hline(yintercept = 0) +
  geom_vline(xintercept = 0) +
  labs(title = "Plot of residuals and lagged residuals", x = "lagged residuals", y = "residuals")

Test 11 Breusch-Godfrey Autocorrelation Test

Question to the test addresses:

Is there serial correlation in the sample?

To use this test:

  • included lagged values in the model

  • residuals are assumed to be stationary and normally distribution with zero mean

  • powerful and general than Durbin-Watson Autocorrelation test

This test is used when there is lagged values of dependent variables in the model, which can not use the Durbin-Watson test. For example, the growth of population in one city or the stock prices in the market. We will use EuStockMarkets to examine this test. We will examine the daily changes of DAX.

library(lmtest)
dax_df <- data.frame(DAX_change = as.numeric(dax_diff))

dax_df <- dax_df %>%
  mutate(DAX_change_lag1 = lag(DAX_change, 1))

dynamic_model <- lm(DAX_change ~ DAX_change_lag1, data = dax_df)
bgtest(dynamic_model, order = 3)

    Breusch-Godfrey test for serial correlation of order up to 3

data:  dynamic_model
LM test = 0.65409, df = 3, p-value = 0.8839

According to this result, the p-value is larger than the critical value 0.05. Therefore, we can not reject the null hypothesis that there is no lagged value in the dependent variables.

Test 12 T-test

Test 12 One-Sample t-test For a Hypothesised Mean

Question to the test addresses:

Is the mean of a sample significantly different from a hypothesised mean?

To use this test:

  • data is assumed to be normally distributed

  • the population standard deviation is unknown

For this test, we will use the built-in dataset sleep.

drug1_data <- sleep %>% 
  filter(group == 1)

t.test(drug1_data$extra, mu = 0, alternative = "two.sided")

    One Sample t-test

data:  drug1_data$extra
t = 1.3257, df = 9, p-value = 0.2176
alternative hypothesis: true mean is not equal to 0
95 percent confidence interval:
 -0.5297804  2.0297804
sample estimates:
mean of x 
     0.75 

According to the result, we can find that the p-value is larger than the critical value 0.05. Therefore, we can not reject the null hypothesis that the drug has no effect on sleep average time.

Test 13: One-sample Wilcoxon Signed-Rank Test

Question to the test addresses:

Is the median of a sample significantly different from a hypothesised value?

To use this test:

  • sample data are assumed not to be normally distributed

  • a nonparametric test

  • alternative method to the one-sample t-test

This test is closely related to the test 12. In order to practice this test, we first examine the distribution of sample dataset that we created.

shapiro.test(drug1_data$extra)

According to the result, the p-value is larger than the critical value 0.05. Therefore, we can not reject the null hypothesis that the sample data is normally distributed. Even though one-sample t-test is better, we can still use the Wilcoxon test here.

wilcox.test(drug1_data$extra, mu = 0, alternative = "two.sided")

    Wilcoxon signed rank test with continuity correction

data:  drug1_data$extra
V = 31, p-value = 0.3433
alternative hypothesis: true location is not equal to 0

According to the result, we can find that the p-value is larger than the critical value 0.05. Therefore, we can not reject the null-hypothesis. We get the same conclusions from t-test and Wilcoxon test.

Test 14 Sign Test for a Hypothesised Median

Question to the test addresses:

Is the median of a sample significantly different from a hypothesised median?

To use this test:

  • nonparametric test

  • even simpler requirements than Wilcoxon test

  • best for description data like better, same, worse

  • less powerful than Wilcoxon test and t-test

We will continue to use the drug data as sample to demonstrate the coding processes. We will need package BSDA to calculate this test.

library(BSDA)

SIGN.test(drug1_data$extra, mu=0, alternative = "two.sided")

    One-sample Sign-Test

data:  drug1_data$extra
s = 5, p-value = 1
alternative hypothesis: true median is not equal to 0
95 percent confidence interval:
 -0.8755556  2.9457778
sample estimates:
median of x 
       0.35 

Achieved and Interpolated Confidence Intervals: 

                  Conf.Level  L.E.pt U.E.pt
Lower Achieved CI     0.8906 -0.2000 2.0000
Interpolated CI       0.9500 -0.8756 2.9458
Upper Achieved CI     0.9785 -1.2000 3.4000

According to the results, we can find that the p-value is larger than the critical value 0.05. Therefore, we can not reject the null hypothesis. Compared to t-test and Wilcoxon test, we can find that the simpler conditions a test requires, the larger p-value we can get.

Test 15 Two-sample t-test for the Difference in Sample Means

Question to the test addresses:

Is the difference between the mean of two samples significantly different from zero?

To use this test:

  • compare means of two independent groups

  • each group is assumed to be normally distribution

  • variances of two groups are equal

In this test, we will use the chickwts dataset which contains the weights of 71 six-week-old chicks fed by different types of feed. Let’s test if there is a significant difference in the final weight of chicks fed by “casein” and “soybean

data(chickwts)
head(chickwts)

chicks_compare <- chickwts %>% 
  filter(feed %in% c("casein","soybean"))
t.test(weight ~ feed, data = chicks_compare, var.equal = TRUE)

    Two Sample t-test

data:  weight by feed
t = 3.3199, df = 24, p-value = 0.002869
alternative hypothesis: true difference in means between group casein and group soybean is not equal to 0
95 percent confidence interval:
  29.18928 125.12024
sample estimates:
 mean in group casein mean in group soybean 
             323.5833              246.4286 

According to this result, we can find that the p-value is smaller than the critical value 0.05. Therefore, we can reject the null hypothesis that there is no difference between the weights from soybean group of chicks and casein group of chicks.

Test 16 Pairwise t-test for the Difference in Sample Means

Question to the test addresses:

Is the difference between the mean of three or more samples significantly different from zero?

To use this test:

  • more than two groups of data

  • all data are assumed to be normally distributed

We will continue use the chickwts dataset. Now we will compare all different types of feed at the same time. Therefore, we need to use the adjust p-value for more accurate results. We will adjust the pool.sd to FALSE for the comparison for test 17. However, we need to remember we do not need to set pool.sd to FALSE in actual uses.

pairwise.t.test(chickwts$weight, chickwts$feed, p.adjust.method = "holm", pool.sd = FALSE)

    Pairwise comparisons using t tests with non-pooled SD 

data:  chickwts$weight and chickwts$feed 

          casein  horsebean linseed meatmeal soybean
horsebean 1.0e-05 -         -       -        -      
linseed   0.00261 0.04808   -       -        -      
meatmeal  0.39465 0.00126   0.17599 -        -      
soybean   0.02817 0.00171   0.59396 0.59396  -      
sunflower 0.82151 2.5e-07   0.00031 0.22207  0.00386

P value adjustment method: holm 

According to the results, we can find that some p-values are varied in the table. For example, we can reject the null hypotheses of casein and horsebeam, and casein and linseed but we can not reject the null hypotheses of casein and meatmeal, and casein and sunflower.

The reason why the p-value of the pair “casein and soybean” is a bit larger than the example in test 15 is that p-value adjustment for multiple comparisons. The “holm” method slightly increases the p-values to reduce the chance of making Type I error.

Test 17 Pairwise t-test with Common Variance

Question to the test addresses:

Is the difference between the mean of three or more samples significantly different from zero?

To use this test:

  • variances are equal across all test groups

  • powerful than test 16 if the assumption is true

The only change for this test is that we set the pool.sd to TRUE.

pairwise.t.test(chickwts$weight, chickwts$feed, p.adjust.method = "holm", pool.sd = TRUE)

    Pairwise comparisons using t tests with pooled SD 

data:  chickwts$weight and chickwts$feed 

          casein  horsebean linseed meatmeal soybean
horsebean 2.9e-08 -         -       -        -      
linseed   0.00016 0.09435   -       -        -      
meatmeal  0.18227 9.0e-05   0.09435 -        -      
soybean   0.00532 0.00298   0.51766 0.51766  -      
sunflower 0.81249 1.2e-08   8.1e-05 0.13218  0.00298

P value adjustment method: holm 

According to the results, we almost get the same answers from test 15 and test 16. However, some changes are observable. For example, the p-value between casein and soybean is slightly larger than the p-value in test 15 but smaller than the p-value in test 16 when pool.sd is set to FALSE.

The reason why three p-values of the pair “casein and soybean are different is that different kinds of variances are used in the calculation. For test 15, we only calculate the deviation between”casein” and “soybean”. In test 17, we actually test the deviations across six groups together, which contains more data. For the test 16, we calculate the test through a separate comparison for each pair without assuming equal variances. This is actually the Welch t-test, which will be discussed in test 18.

Test 18 Welch t-test for the Difference in Sample Means

Question to the test addresses:

Is the difference between the mean of two sample groups significantly different from zero?

To use this test:

  • not assumed to be equal variances

The code for this test is as same as what we did in 16 but only with two groups of feeds.

feeds_to_compare <- chickwts %>%
  filter(feed %in% c("casein", "soybean"))

t.test(weight ~ feed, data = feeds_to_compare, var.equal = FALSE)

    Welch Two Sample t-test

data:  weight by feed
t = 3.2743, df = 21.635, p-value = 0.003521
alternative hypothesis: true difference in means between group casein and group soybean is not equal to 0
95 percent confidence interval:
  28.23823 126.07129
sample estimates:
 mean in group casein mean in group soybean 
             323.5833              246.4286 

According to the results, we can find that p-value is smaller than the critical value 0.05. Therefore, we can reject the null hypothesis that there is no difference in the final weights of chicks between two types of feeds.

Test 19 Paired t-test for the Difference in Sample Means

Question to the test addresses:

Is the difference between the mean of two related samples significantly different from zero?

To use this test:

  • measure same subject twice, before and after

  • subjects are assumed to be drawn from a population with a normal distribution

We will use the sleep dataset to examine the drug effects on sleep duration.

drug1_sleep <- sleep$extra[sleep$group == 1]

drug2_sleep <- sleep$extra[sleep$group == 2]

t.test(drug1_sleep, drug2_sleep, paried = TRUE, var.equal = TRUE)

    Two Sample t-test

data:  drug1_sleep and drug2_sleep
t = -1.8608, df = 18, p-value = 0.07919
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -3.363874  0.203874
sample estimates:
mean of x mean of y 
     0.75      2.33 

According to the results, we find that the p-value is larger than the critical value 0.05. Therefore, we can not reject the null hypothesis that there is no difference on the mean effect between drug 1 and drug 2 on the same person.

Test 20 Matched Pairs Wilcoxon Test

Question to the test addresses:

Is the difference between the mean of two related samples significantly different from zero?

To use this test:

  • data are paired

  • can not assume the differences are normally distributed

  • on ranks of differences

We will still use the sleep dataset in this test.

wilcox.test(drug1_sleep, drug2_sleep, paired = TRUE)

    Wilcoxon signed rank test with continuity correction

data:  drug1_sleep and drug2_sleep
V = 0, p-value = 0.009091
alternative hypothesis: true location shift is not equal to 0

According to the result, we can find that the p-value is smaller than the critical value 0.05. Therefore, we can reject the null hypothesis that there is no difference on the drug effects between drug 1 and drug 2 on the same person.

Compared to the result in Test 19, we get the opposite conclusions. Test 19 indicates that we can not reject the null hypothesis but Test 20 indicates that we can do it. The statistical reason is that the Wilcoxon test is often more powerful than the t-test when the data is not perfectly normally distributed or when there are outliers. The Wilcoxon test works with the ranks of the data, which makes it less sensitive to one or two unusually large or small values. In this sleep dataset, the differences might not be perfectly normal, giving the Wilcoxon test an advantage in detecting a real effect.

Test 21 Pairwise Paired t-test for the Difference in Sample Means

Question to the test addresses:

Is the difference between the mean of two samples significantly different from zero, when tested across multiple pairs?

To use this test:

  • multiple samples

  • matched pairs experimental design

  • subjects are assumed to be normally distributed

We will use the built-in dataset iris to examine the difference in the length of sepal. The iris dataset contains measurements for 50 flowers from 3 different species. Let’s pretend for this exercise that these aren’t three separate species, but are instead measurements of the same 50 flowers at three different points in time (Time 1, Time 2, Time 3). This lets us practice a paired analysis.

pairwise.t.test(iris$Sepal.Length, iris$Species, paired = TRUE, p.adjust.method = "holm")

    Pairwise comparisons using paired t tests 

data:  iris$Sepal.Length and iris$Species 

           setosa  versicolor
versicolor 2.5e-13 -         
virginica  < 2e-16 3.0e-06   

P value adjustment method: holm 

According to the result, we can find that the p-values across all pairs are smaller than the critical value 0.05. Therefore, we can reject the null hypothesis that there is no significant difference in the length of sepal between any of the three time points.

Test 22 Pairwise Wilcox Test for the Difference in Sample Means

Question to the test addresses:

Is the difference between the mean of two samples significantly different from zero, when tested across multiple pairs?

To use this test:

  • same with conditions in test 21

  • can not assume to be normally distributed

We keep our assumption that we set in test 21.

pairwise.wilcox.test(iris$Sepal.Length, iris$Species, paired = TRUE, p.adjust.method = "holm")

    Pairwise comparisons using Wilcoxon signed rank test with continuity correction 

data:  iris$Sepal.Length and iris$Species 

           setosa  versicolor
versicolor 7.2e-09 -         
virginica  3.4e-09 1.9e-05   

P value adjustment method: holm 

According to this result, we can get the same conclusion based on the p-value.

Test 23 Two-sample Dependent Sign Rank Test for Difference in Medians

Question to the test addresses:

Is the difference between the median of two related samples significantly from zero?

To use this test:

  • each subject is measured twice, before and after

  • a matched pairs experimental design

  • continuous distribution

We will use the sleep dataset. We will also need the function SIGN.test() from BSDA package.

drug1_sleep <- sleep$extra[sleep$group == 1]
drug2_sleep <- sleep$extra[sleep$group == 2]

SIGN.test(drug1_sleep, drug2_sleep)

    Dependent-samples Sign-Test

data:  drug1_sleep and drug2_sleep
S = 0, p-value = 0.003906
alternative hypothesis: true median difference is not equal to 0
95 percent confidence interval:
 -2.2053333 -0.8648889
sample estimates:
median of x-y 
         -1.3 

Achieved and Interpolated Confidence Intervals: 

                  Conf.Level  L.E.pt  U.E.pt
Lower Achieved CI     0.8906 -1.8000 -1.0000
Interpolated CI       0.9500 -2.2053 -0.8649
Upper Achieved CI     0.9785 -2.4000 -0.8000

According to the result, we can find the p-value is smaller than the critical value. Therefore, we can reject the null hypothesis.

Test 24 Wilcoxon Rank Sum Test for the Difference in Medians

Question to the test addresses:

Is the difference between the median of two samples significantly different from zero?

To use this test:

  • Data are not assumed to be normally distributed

  • Two independent groups

  • works with rank of the data

We will use the chickwts one last time to compare it with the t-tests.

feeds_to_compare <- chickwts %>% 
  filter(feed %in% c("casein", "soybean"))

wilcox.test(weight ~ feed, data = feeds_to_compare)

    Wilcoxon rank sum test with continuity correction

data:  weight by feed
W = 138, p-value = 0.005919
alternative hypothesis: true location shift is not equal to 0

According to the result, we can find that the p-value is smaller than the critical value. Therefore, we can reject the null hypothesis.

Test 25-31 A Deep Dive into Randomness

Test 25 Wald-Wolfowitz Runs Test for Dichotomous Data

This test is used to check for randomness in a sequence of binary events. Binary data means that data with only two categories, like Yes/No, or 0/1.

This test detects the runs in a sequence of data. A run means the uninterrupted sequence of the same event. For example, in the sequence 1, 1, 1, 0, 0, 1, 0, 0, 0, there are 4 runs (111, 00, 1, 000). If there are too few or too many runs, it suggests the sequence isn’t random.

We will use the runs.test() from tseries package.

if (!require("tseries")) {
  install.packages("tseries")
  library(tseries)
}

binary_sequence <- factor(c(1,1,0,0,1,0,1,1,1,0,0,0))

runs.test(binary_sequence)

    Runs Test

data:  binary_sequence
Standard Normal = -0.60553, p-value = 0.5448
alternative hypothesis: two.sided

According to this result, we can find that the p-value is larger than the critical value 0.05. Therefore, we can not reject the null hypothesis that our binary sequence is random.

Test 26 Wald-Wolfowitz Runs Test for Continuous Data

This test extends the test 25 into continuous data. Question to this test addresses:

Is the sequence of observations in a sample radomly distributed?

It works for continuous data.

We will use the runs.test() from the lawstat package for this.

if (!require("lawstat")) {
  install.packages("lawstat")
  library(lawstat)
}

continuous_sequence <- c(1.8, 2.3, 1.5, 2.9, 1.1, 3.5, 0.9)

runs.test(continuous_sequence)

    Runs Test - Two sided

data:  continuous_sequence
Standardized Runs Statistic = 2.7386, p-value = 0.00617

According to this result, we can find that the p-value is smaller than critical value 0.05. Therefore, we can reject the null hypothesis that our continuous sequence is random.

Test 27 Bartels Test of Randomness in a Sample

Question to the test addresses:

Is the sequence of observations in a sample randomly distributed?

Bartels test is a powerful alterantive to the Wald-Wolfowitz runs test for continuous data. It’s based on the ranks of data rather than just their position relative to the median.

The function is bartels.test() from the same lawstat package. We will use the same continuous in the test 26 in this test.

bartels.test(continuous_sequence)

    Bartels Test - Two sided

data:  continuous_sequence
Standardized Bartels Statistic = 1.6536, RVN Ratio = 3.25, p-value =
0.09821

According to the result, we can find that p-value is larger than the critical value 0.05. Therefore, we can not reject the null hypothesis that our continuous sequence is random.

The Wald-Wolfowitz test gave a p-value of 0.006 (significant), while the Bartels test gave 0.098 (not significant). While the Barlets test is often more powerful, it’s not a universal rule. Different tests are sensitive to different kinds of non-random patterns. In our example, the very short sequence, they way the two tests calculate their statistics led them to different conclusions.

Test 28 & 29 Ljung-Box and Box-Pierce Tests

Both the Ljung-Box and Box-Pierce tests check for autocorrelation in a time series.

Question to these tests address:

Is the sequence of observations in a sample randomly distributed?

These tests check if the autocorrelations between the series and its past values are all zero. The Ljung-Box test is a refinement of the Box-Pierce test and is generally preferred for small sample sizes.

We will use the built-in Nile dataset contains measurements of the flow of the river Nile from 1871-1970.

plot(Nile)

Box.test(Nile, lag = 10, type = "Ljung-Box")

    Box-Ljung test

data:  Nile
X-squared = 88.127, df = 10, p-value = 1.255e-14
Box.test(Nile, lag =10, type = "Box-Pierce")

    Box-Pierce test

data:  Nile
X-squared = 83.229, df = 10, p-value = 1.166e-13

According to these results, we can find that the p-values are both smaller than the critical value 0.05. Therefore, we can reject the null hypothesis that the measurements of the river Nile is random.

Test 30 BDS test

Question to the test addresses:

Is a time series independent and identically distributed?

To use this test:

  • detect complex and non-linear patterns

  • single time series

We will continue to use the Nile dataset and check if there is any non-random or non-linear patterns.

bds.test(Nile)

     BDS Test 

data:  Nile 

Embedding dimension =  2 3 

Epsilon for close points =   84.6138 169.2275 253.8413 338.4550 

Standard Normal = 
      [ 84.6138 ] [ 169.2275 ] [ 253.8413 ] [ 338.455 ]
[ 2 ]      2.9223       6.9347       6.7724      5.6218
[ 3 ]      1.9868       7.4144       7.6433      6.5196

p-value = 
      [ 84.6138 ] [ 169.2275 ] [ 253.8413 ] [ 338.455 ]
[ 2 ]      0.0035            0            0           0
[ 3 ]      0.0469            0            0           0

According to the result, we can find that all p-values are smaller than the critical value 0.05. Therefore, we can reject the null hypothesis that the Nile dataset is independent and identically distributed. It suggests the patterns in the Nile dataset are more complex and maybe non-linear.

Test 31 Wald-Wolfowitz Two-Sample Run test

Question to the test addresses:

Do two independent samples come from populations having the same distribution?

To use this test:

  • combining two samples together

  • ranking with the run test

We will use the Nile dataset to see whether the first 50 years are different from the last 50 years.

nile_first_50 <- Nile[1:50]
nile_last_50 <- Nile[51:100]
plot(nile_first_50)

plot(nile_last_50)

combined_nile <- c(nile_first_50,nile_last_50)
group_labels <- factor(c(rep("first", 50), rep("last", 50)))

sorted_groups <- group_labels[order(combined_nile)]
tseries::runs.test(sorted_groups)

According to the result, we can find that the p-value is smaller than the critical value 0.05. Therefore, we can reject the null hypothesis that there is no difference between the first 50 years and last 50 years. The test suggests that the two samples are not randomly mixed, which means the distribution of the Nile’s flow in the first 50 years is likely different from its distribution in the last 50 years.

Variances and Dispersion

Test 32 Mood’s Test

Question to the test addresses:

Do two independent samples come from the same distribution?

To use this test:

  • two samples are assumed to have same medians and shape

We will compare the spread of weights for chicks fed “casein” versus those fed “sunflower”. Visually, their average weights look similar, but is the consistency of the weight gain the same?

we can use the mood.test() function.

casein_v_sunflower <- chickwts %>%
  filter(feed %in% c("casein", "sunflower"))

ggplot(casein_v_sunflower, aes(x = feed, y = weight, fill = feed)) +
  geom_boxplot() +
  labs(title = "Comparison of Chick Weights by Feed Type",
       x = "Feed Type",
       y = "Weight (grams)") +
  theme_minimal()

mood.test(weight ~ feed, data = casein_v_sunflower)

    Mood two-sample test of scale

data:  weight by feed
Z = 1.3501, p-value = 0.177
alternative hypothesis: two.sided

According to the result, we can find that the p-value is larger than the critical value 0.05. Therefore, we can not reject the null hypothesis that these two independent samples come from the same distribution.

Test 33 F-test of Equality of Variances

Question to the test addresses:

Are the variances of two samples equal?

To use this test:

  • highly sensitive to the data being normally distributed

  • parametric test, very powerful

We will use the F-test on the same two groups: “casein” vs. “sunflower”. This will let us compare the result from a parametric test (F-test) to the nonparametric one (Mood’s test). The function for F-test is var.test().

casein_v_sunflower <- chickwts %>% 
  filter(feed %in% c("casein", "sunflower"))

var.test(weight ~ feed, data = casein_v_sunflower)

    F test to compare two variances

data:  weight by feed
F = 1.7408, num df = 11, denom df = 11, p-value = 0.3718
alternative hypothesis: true ratio of variances is not equal to 1
95 percent confidence interval:
 0.5011282 6.0469059
sample estimates:
ratio of variances 
          1.740769 

According to the result, we can find that the p-value is larger than the critical value. Therefore, we can not reject the null hypothesis that the variances of casein group and sunflower group are equal.

Test 34 Pitman-Morgan Test

Question to the test addresses:

Are the variances of two correlated sample equal?

To use this test:

  • paired data

  • testing the correlation between sum and variances

  • highly sensitive to the data being normally distributed

We will use sleep dataset again, as it contains paired data (each of the 10 subjects was tested on two different drugs). We can test if the variance in “extra sleep” was different for Drug 1 compared to Drug 2.

The function for this is pitman.morgan.test.default() from the PairedData package.

if (!require("PairedData")) {
  install.packages("PairedData")
  library(PairedData)
}
pitman.morgan.test.default(drug1_sleep, drug2_sleep)

    Paired Pitman-Morgan test

data:  drug1_sleep and drug2_sleep
t = -0.52636, df = 8, p-value = 0.6129
alternative hypothesis: true ratio of variances is not equal to 1
95 percent confidence interval:
 0.3080221 2.0691727
sample estimates:
variance of x variance of y 
     3.200556      4.009000 

According to the result, we can find that the p-value is larger than the critical value 0.05. Therefore, we can not reject the null hypothesis that the variances from drug 1 and drug 2 are equal.

Test 35-40 The Homogeneity of Variance Family

All these series of tests aim to answer the same question:

Do multiple independent samples come from populations with equal variances?

Test 35 Ansari-Bradley Test

To use this test:

  • data are assumed to be continuous

  • data are measured at ordinary scale

We will use the full chickwts dataset, which has six feed groups, to test if the variance in weight is the same across all of them. We’ll start with the Ansari-Bradley Test.

casein_v_sunflower <- chickwts %>%
  filter(feed %in% c("casein", "sunflower"))

ansari.test(weight ~ feed, data = casein_v_sunflower)

    Ansari-Bradley test

data:  weight by feed
AB = 64.5, p-value = 0.1177
alternative hypothesis: true ratio of scales is not equal to 1

According to the result, we can find that p-value is larger than the critical value 0.05. Therefore, we can not reject the null hypothesis that these two samples have the same variances.

Test 36 Bartlett Test

To use this test:

  • sensitive to data being normal distribution

We will use chickwts dataset to compare variances from all feeds.

bartlett.test(weight ~ feed, data = chickwts)

    Bartlett test of homogeneity of variances

data:  weight by feed
Bartlett's K-squared = 3.2597, df = 5, p-value = 0.66

According to the results, we can find that the p-value is larger than the critical value. Therefore, we can not reject the null hypothesis that variances from all feed are the same.

Test 37 Fligner-Killeen Test

  • nonparametric test

  • more robust

  • data can be assumed not to be normally distributed

We will compare the results from Fligner-Kileen test and Bartlett test to see anything different.

fligner.test(weight ~ feed, data = chickwts)

    Fligner-Killeen test of homogeneity of variances

data:  weight by feed
Fligner-Killeen:med chi-squared = 3.8109, df = 5, p-value = 0.577

According to the results, we get the exact same conclusion with Bartlett test.

Test 38 Levene’s Test of Equality of Variance

To use this test:

  • data are assumed not to be normally distributed

The function leveneTest() is in the car package, which we’ve used before. Let’s run it on our chickwts data to see if our conclusion holds a third time.

if (!require("car")) {
  install.packages("car")
  library(car)
}

leveneTest(weight ~ feed, data = chickwts)
Levene's Test for Homogeneity of Variance (center = median)
      Df F value Pr(>F)
group  5  0.7493 0.5896
      65               

According to the results, we get the same result again.

Test 39 Cochran’s C Test

Question to the test addresses:

Is single largest variance among a group of samples an outlier?

To use this test:

  • equal sample size across all groups

  • measure the largest variances as the outliers

We’ll use the InsectSprays data and the cochran.test function from the outliers package.

if (!require("outliers")) {
  install.packages("outliers")
  library(outliers)
}

summary(InsectSprays)
     count       spray 
 Min.   : 0.00   A:12  
 1st Qu.: 3.00   B:12  
 Median : 7.00   C:12  
 Mean   : 9.50   D:12  
 3rd Qu.:14.25   E:12  
 Max.   :26.00   F:12  
cochran.test(count ~ spray, data = InsectSprays)

    Cochran test for outlying variance

data:  count ~ spray
C = 0.41832, df = 12, k = 6, p-value = 0.004435
alternative hypothesis: Group F has outlying variance
sample estimates:
        A         B         C         D         E         F 
22.272727 18.242424  3.901515  6.265152  3.000000 38.606061 

According to the results, we can find that the p-value is smaller than the critical value. Therefore, we can reject the null hypothesis that there are no variances as outliers from all groups. The variance of spray F is significantly larger than the variances of the other sprays.

Test 40 Brown-Forsythe Test

  • use medians for test

  • more robust and general-purpose

We will run this test on InsectSprays data to see what it says about the overall equality of variances. The function is levene.test() from the lawstat package, and we specify location = "median" to make it a Brown-Forsythe test.

levene.test(InsectSprays$count, InsectSprays$spray, location = "median")

    Modified robust Brown-Forsythe Levene-type test based on the absolute
    deviations from the median

data:  InsectSprays$count
Test Statistic = 3.8214, p-value = 0.004223

According to the result, we can find that the p-value is smaller than the critical value. We can reject the null hypothesis that the variances across all groups are the same.

Test 41 Mauchly’s Sphericity Test

Question to the test addresses:

Are the variances of the differences between all possible pairs of groups in a repeated measures analysis of variance equal?

To use this test:

  • variances of the differences of comparison groups need to be equal

  • repeated measures for ANOVA analysis

We will use ChickWeight and sleep to continue practice this test.

sleep_wide <- reshape(sleep, idvar = "ID", timevar = "group", direction = "wide", sep = "_")
sleep_matrix <- as.matrix(sleep_wide[,c('extra_1', 'extra_2')])

lm_sleep <- lm(sleep_matrix ~ 1)
mauchly.test(lm_sleep, X = ~1)

    Mauchly's test of sphericity
    Contrasts orthogonal to
    ~1


data:  SSD matrix from lm(formula = sleep_matrix ~ 1)
W = 1, p-value = 1
chick_subset <- ChickWeight[ChickWeight$Time %in% c(0,2,4,6),]
chick_subset <- chick_subset[chick_subset$Chick %in% 1:10,]

chick_wide <- reshape(chick_subset, idvar = "Chick", timevar = "Time", direction = "wide", sep = "_")
chick_matrix <- as.matrix(chick_wide[,c("weight_0", "weight_2", "weight_4", "weight_6")])
chick_matrix <- na.omit(chick_matrix)

lm_chick <- lm(chick_matrix ~ 1)
mauchly.test(lm_chick, X= ~1)

    Mauchly's test of sphericity
    Contrasts orthogonal to
    ~1


data:  SSD matrix from lm(formula = chick_matrix ~ 1)
W = 0.53701, p-value = 0.4439

According to the results, we can find that the p-value in practice 1 is 1 and the p-value in practice 2 is 0.4439. Both of them are larger than the critical value 0.05. For the practice 1, there are only two conditions in the test so there is no variances to compare. For the practice 2, we can not reject the null hypothesis that the variances of comparison groups are equal.

Test 42 Binomial Test

Question to the test addresses:

Do the proportion on of individuals falling in each category differ from chance? Or does the proportion on of individuals falling into each category differ from some pre-specified probabilities of falling into those categories?

A simple way to understand this test is that if we flip a coin 30 times and get 25 heads, this test can tell us the exact probability of that happening with a fair coin.

binom.test(x = 25, n = 30, p = 0.5)

    Exact binomial test

data:  25 and 30
number of successes = 25, number of trials = 30, p-value = 0.0003249
alternative hypothesis: true probability of success is not equal to 0.5
95 percent confidence interval:
 0.6527883 0.9435783
sample estimates:
probability of success 
             0.8333333 

According to the result, we can find that the p-value is smaller than the critical value 0.05. Therefore, we can reject the null hypothesis that the true probability is 0.5 for this example. The true probabilities are from 0.645 to 0.94.

Test 43 One-Sample Proportions Test

Question to the test addresses:

Is the observed proportion from a random experiment equal to some pre-specified probability?

This test is similar with Binomial test. It is suitable for large sample size. We have 100 people in a survey and 52 of them believe they prefer option A. We can test whether this is significantly from a 50% of market share.

prop.test(x = 52, n = 100, p =0.5)

    1-sample proportions test with continuity correction

data:  52 out of 100, null probability 0.5
X-squared = 0.09, df = 1, p-value = 0.7642
alternative hypothesis: true p is not equal to 0.5
95 percent confidence interval:
 0.4183183 0.6201278
sample estimates:
   p 
0.52 

According to this result, we can find that the p-value is larger than the critical value 0.05. Therefore, we can not reject the null hypothesis that our survey result shows the same proportion of market share.

Test 44 One-Sample Poisson Test

Question to the test addresses:

Is the rate parameter of a Poisson distributed sample significantly different from a hypothesized value?

To use this test:

  • count data

Researchers observed 6 cases of a particular cancer in a group of relatives, but based on the general population, they only expected 6.2 cases. Is the observed number significantly different from the expected number?

poisson.test(x = 6, T = 6.2)

    Exact Poisson test

data:  6 time base: 6.2
number of events = 6, time base = 6.2, p-value = 1
alternative hypothesis: true event rate is not equal to 1
95 percent confidence interval:
 0.3551442 2.1063668
sample estimates:
event rate 
 0.9677419 

According to the result, we can find that the p-value is larger than the critical value. Therefore, we can not reject the null hypothesis that the observed number is significant different from the expected number.

Test 45 Pairwise Comparison of Proportions Test

Question to the test addresses:

Is the difference between the pairwise proportions in three or more samples significant?

To use this test:

  • three or more than three groups

Suppose we have data from six different hospital wards on the proportion of patients who recovered after a treatment.

Ward Recovered Not Recovered
s1 95 106
s2 181 137
s3 76 85
s4 13 29
s5 11 26
s6 201 179
recovery_data <- matrix(c(95, 106, 181, 137, 76, 85, 13, 29, 11, 26, 201, 179),
                      ncol = 2, byrow = TRUE)


colnames(recovery_data) <- c("Recovered", "Not Recovered")
rownames(recovery_data) <- c("s1", "s2", "s3", "s4", "s5", "s6")

pairwise.prop.test(recovery_data)

    Pairwise comparisons using Pairwise comparison of proportions 

data:  recovery_data 

   s1    s2    s3    s4    s5   
s2 0.437 -     -     -     -    
s3 1.000 0.553 -     -     -    
s4 0.658 0.039 0.658 -     -    
s5 0.658 0.042 0.658 1.000 -    
s6 1.000 1.000 1.000 0.146 0.146

P value adjustment method: holm 

According to the result, we can find that the p-values between s2 and s4, s2 and s5 are smaller than the critical value. Therefore, we can only reject the null hypothesis between these two groups that s2 and s4, s2 and s5 are significantly different.

Test 46 Two-Sample Poisson Test

Question to the test addresses:

Is the rate parameter of a Poisson distributed sample significantly different from another?

This is the two-sample version of the Poisson test.

To use this test:

  • two independent samples

  • compare the rate of events

We will test two samples:

  • Sample 1: Observed 10 events over a “time base” or exposure of 20,000 units.

  • Sample 2: Observed 2 events over a “time base” or exposure of 17,877 units.

poisson.test(c(10,2),c(20000,17877))

    Comparison of Poisson rates

data:  c(10, 2) time base: c(20000, 17877)
count1 = 10, expected count1 = 6.3363, p-value = 0.04213
alternative hypothesis: true rate ratio is not equal to 1
95 percent confidence interval:
  0.9524221 41.9509150
sample estimates:
rate ratio 
   4.46925 

According to the result, we can find that the p-value is smaller than the critical value. Therefore, we can reject the null hypothesis that the rate of parameters of these two samples are significantly different.

Test 47 Multiple Sample Proportions Test

Question to the test addresses:

Is the difference between the observed proportions from two or more samples significantly different from zero?

To use this test:

  • two or more independent groups

  • compare the proportions of successes

We will use two groups to practice this test:

  • Group 1 (Male Faculty): 18 out of 30 were trained at top-tier schools (18 successes, 30 trials).

  • Group 2 (Female Faculty): 17 out of 24 were trained at top-tier schools (17 successes, 24 trials).

prop.test(c(18,17),c(30,24))

    2-sample test for equality of proportions with continuity correction

data:  c(18, 17) out of c(30, 24)
X-squared = 0.29335, df = 1, p-value = 0.5881
alternative hypothesis: two.sided
95 percent confidence interval:
 -0.3984195  0.1817529
sample estimates:
   prop 1    prop 2 
0.6000000 0.7083333 

According to the result, we can find that the p-value is larger than the critical value. Therefore, we can not reject the null hypothesis that there is differences between the rate of successes in the two groups.

Test 48 Chi-Squared Test for Linear Trend

Question to the test addresses:

Is there a linear trend in the proportions across multiple ordered categories?

To use this test:

  • three or more ordered groups

  • find a linear trend in the proportions of success

We have three groups with increasing dosage levels.

  • Group 1 (10mg): 10 successes out of 50 trials.

  • Group 2 (20mg): 17 successes out of 50 trials.

  • Group 3 (30mg): 25 successes out of 50 trials.

success <- c(10, 17, 25)

totals <- c(50, 50, 50)

prop.trend.test(success, totals)

    Chi-squared Test for Trend in Proportions

data:  success out of totals ,
 using scores: 1 2 3
X-squared = 9.9343, df = 1, p-value = 0.001622

According to the result, we can find that the p-value is smaller than the critical value. Therefore, we can reject the null hypothesis that there is no linear trend.

Test 49 Pearson’s Paired Chi-Squared Test

Question to the test addresses:

Are the paired observations on two variables in a contingency table independent of each other?

To use this test:

  • two categorical variables

We have a contingency table showing the voting patterns of 100 citizens, categorized by gender and political party.

Gender Labour Conservative
Male 20 30
Female 30 20

We want to test if a person’s gender is independent of their choice of political party.

voting_data <- as.table(rbind(c(20, 30), c(30, 20)))

dimnames(voting_data) <- list(gender = c("Male", "Female"), party = c("Labour", "Conservative"))
chisq.test(voting_data, correct = FALSE)

    Pearson's Chi-squared test

data:  voting_data
X-squared = 4, df = 1, p-value = 0.0455

According to the result, we can find that p-value is smaller than the critical value. Therefore, we can reject the null hypothesis that the person’s gender is independent of their choice of party.

Test 50 Fisher’s Exact Test

Question to the test addresses:

Are the paired observations on two variables in a contingency table independent of each other?

To use this test:

  • small sample size

  • two categorical variables

We have a contingency table showing the voting patterns of 100 citizens, categorized by gender and political party.

Gender Labour Conservative
Male 2 3
Female 3 2

We want to test if a person’s gender is independent of their choice of political party.

voting_data <- as.table(rbind(c(2, 3), c(3, 2)))

dimnames(voting_data) <- list(gender = c("Male", "Female"), party = c("Labour", "Conservative"))
fisher.test(voting_data)

    Fisher's Exact Test for Count Data

data:  voting_data
p-value = 1
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
 0.01931867 9.42971111
sample estimates:
odds ratio 
 0.4831013 

According to the result, we can find that the p-value is larger than the critical value. Therefore, we can not reject the null hypothesis. There is no significantly association between a person’s gender and their choice of political party.

Test 51 Cochran-Mantel-Haenszel Test

Question to the test addresses:

Is there a relationship between two categorical variables after adjusting for control variables?

To use this test:

  • More advanced chi-squared test

  • test relationships between two categorical variables and control for a third categorical variable

We will create a treatment example from the book. We want to see if a treatment (“Drug” vs. “Placebo”) is associated with a response (“Improved” vs. “No Change”), while controlling for sex (“Male” vs. “Female”).

treatment_data <- array(
  c(12,16,7,19,
    16,11,5,20),
  dim = c(2,2,2),
  dimnames = list(
    Treatment = c("Drug","Placebo"),
    Response = c("Improved","No Change"),
    Sex = c("Male","Female")
  )
)
ftable(treatment_data)
                    Sex Male Female
Treatment Response                 
Drug      Improved        12     16
          No Change        7      5
Placebo   Improved        16     11
          No Change       19     20
mantelhaen.test(treatment_data)

    Mantel-Haenszel chi-squared test with continuity correction

data:  treatment_data
Mantel-Haenszel X-squared = 7.1983, df = 1, p-value = 0.007297
alternative hypothesis: true common odds ratio is not equal to 1
95 percent confidence interval:
 1.445613 7.593375
sample estimates:
common odds ratio 
         3.313168 

According to the result, we can find that the p-value is smaller than the critical value 0.05. Therefore, we can reject the null hypothesis that there is no relationship between the treatment and response even after controlling for sex.

Test 52 McNemar’s Test

Question to the test addresses:

Is there a difference between paired proportions?

To use this test:

  • paired or matched categorical data

  • same subject twice and the outcome is binary (yes/no)

  • suitable for “before and after” test

From the book, we create a table for the diagnostic tests. We are comparing two diagnostic tests for tuberculosis (sputum culture & chest radiography) on the same group of patients.

diagnostic_data <- matrix(
  c(59,4,128,20),
  nrow = 2,
  dimnames = list(
    "Radiography" = c("Positive","Negative"),
    "Sputum" = c("Positive", "Negative"))
)
ftable(diagnostic_data)
            Sputum Positive Negative
Radiography                         
Positive                 59      128
Negative                  4       20
mcnemar.test(diagnostic_data)

    McNemar's Chi-squared test with continuity correction

data:  diagnostic_data
McNemar's chi-squared = 114.61, df = 1, p-value < 2.2e-16

According to the result, we can find that the p-value is smaller than the critical value. Therefore, we can reject the null hypothesis that two tests have the same proportion of positive results.

Test 53 Equal Means in a One-way Layout (ANOVA)

Question to the test addresses:

Do three or more samples come from populations with the same mean?

To use this test:

We will comeback to the chickwts dataset (Let’s say “thank you chicks!”) and compare the effects of six different feeds.

oneway.test(weight ~ feed, data= chickwts, var.equal = TRUE)

    One-way analysis of means

data:  weight and feed
F = 15.365, num df = 5, denom df = 65, p-value = 5.936e-10

According to the result, we can find that the p-value is smaller than the critical value. Therefore, we can reject the null hypothesis that there is no significant difference in the mean weight of chicks across six different groups.

The ANOVA test tells us that at least one group is different from others, but it doesn’t tell us which specific groups are different. To find that out, we would need to perform a follow-up test, like the Test 17 Pairwise t-test with Common Variance.

Test 54 Welch-test for more than two samples (Welch’s ANOVA)

Question to the test addresses:

Do your three or more samples come from populations with the same mean?

To use this test:

  • do not assume equal variances across all groups

  • more robust alternative to the standard ANOVA test

Therefore, we only need to set the var.euqal = FALSE.

oneway.test(weight ~ feed, data= chickwts, var.equal = FALSE)

    One-way analysis of means (not assuming equal variances)

data:  weight and feed
F = 19.662, num df = 5.000, denom df = 29.952, p-value = 1.177e-08

According to the result, we can find that the p-value is smaller than the critical value. Therefore, we can reject the null hypothesis. Comparing with the result from test 53, we can find that the Welch’s ANOVA test has higher F value and larger p value than the standard ANOVA test as it is more robust with fewer constraints.

Test 55 Kruskal-Wallis Rank Sum Test

Question to the test addresses:

Do your three or more samples come from populations with the same mean?

To use this test:

kruskal.test(weight ~ feed, data = chickwts)

    Kruskal-Wallis rank sum test

data:  weight by feed
Kruskal-Wallis chi-squared = 37.343, df = 5, p-value = 5.113e-07

According to the result, we can find that p-value is smaller than the critical value. Therefore, we can reject the null hypothesis.

Kruskal-Wallis Rank Sum test has even fewer constraints. Therefore, the p-value is larger than the Welch’s ANOA.

Test 56 Friedman’s Test

Question to the test addresses:

Are the distributions from various groups the same across repeated measures?

To use this test:

Friedman Test in R requires matrix data. Therefore, we will create the sample data based on the book.

diet_data <- matrix(c(
  8, 8, 7,  7, 6, 6,  6, 8, 6,  8, 9, 7,
  5, 8, 5,  9, 7, 7,  7, 7, 7,  8, 7, 7,
  8, 6, 8,  7, 6, 6,  7, 8, 6,  9, 9, 6
), nrow = 12, byrow = TRUE,
dimnames = list(
  Subject = 1:12,
  Diet = c("Healthy Balanced","Low Fat","Low Carb")
))

ftable(diet_data)
        Diet Healthy Balanced Low Fat Low Carb
Subject                                       
1                           8       8        7
2                           7       6        6
3                           6       8        6
4                           8       9        7
5                           5       8        5
6                           9       7        7
7                           7       7        7
8                           8       7        7
9                           8       6        8
10                          7       6        6
11                          7       8        6
12                          9       9        6
friedman.test(diet_data)

    Friedman rank sum test

data:  diet_data
Friedman chi-squared = 7.6, df = 2, p-value = 0.02237

According to the result, we can find that the p-value is smaller than the critical value. Therefore, we can reject the null hypothesis that there is no difference in the perceived energy levels across the three diets.

Test 57 Quade Test

Question to the test addresses:

Are the distributions from various groups the same across repeated measures?

To use this test:

  • related (paired) samples

  • more powerful than the Friedman test

  • small number of groups

quade.test(diet_data)

    Quade test

data:  diet_data
Quade F = 3.9057, num df = 2, denom df = 22, p-value = 0.03535

According to the result, we can find that the p-value is smaller than the critical value. Therefore, we can reject the null hypothesis that there is no difference in the perceived energy levels across the three diets.

Testing for Normality

Test 58 D’Agostino Test of Skewness

Question to the test addresses:

Is the data skewed (symmetric or long tail on one side)?

To use this test:

  • for normality assumption

  • looking for Skewness (symmetric, long tail)

if (!require("moments")) {
  install.packages("moments")
  library(moments)
}

set.seed(123)
normal_data <- rnorm(100)
plot(normal_data)

agostino.test(normal_data)

    D'Agostino skewness test

data:  normal_data
skew = 0.060499, z = 0.262698, p-value = 0.7928
alternative hypothesis: data have a skewness

According to the result, we can find that the p-value is larger than the critical value. Therefore, we can not reject the null hypothesis that the data is not skewed.

Test 59 Anscombe-Glynn Test of Kurtosis

Question to the test addresses:

Does the sample exhibit more (or less) kurtosis relative to the normal distribution?

Kurtosis: Does the data have “heavy” or “light” tails compared to a normal distribution?

A distribution with high kurtosis has a sharper peak and heavier tails (meaning more outliers are likely), while a distribution with low kurtosis is flatter with lighter tails.

if (!require("moments")) {
  install.packages("moments")
  library(moments)
}

set.seed(123)
normal_data <- rnorm(100)
plot(normal_data)

anscombe.test(normal_data)

    Anscombe-Glynn kurtosis test

data:  normal_data
kurt = 2.838947, z = -0.059837, p-value = 0.9523
alternative hypothesis: kurtosis is not equal to 3

According to the result, the p-value is larger than the critical value. Therefore, we can not reject the null hypothesis that the data has the same kurtosis as a normal distribution.

Test 60 Bonett-Seier Test of Kurtosis

Question to the test addresses:

Does the sample exhibit more (or less) kurtosis relative to the normal distribution?

To use this test:

  • use Geary’s measure to measure kurtosis

  • run multiple tests for the same property to improve confidence

Now we still use our previous normal_data here.

bonett.test(normal_data)

    Bonett-Seier test for Geary kurtosis

data:  normal_data
tau = 0.72928, z = -0.23812, p-value = 0.8118
alternative hypothesis: kurtosis is not equal to sqrt(2/pi)

According to the result, the p-value is larger than the critical value. Therefore, we can not reject the null hypothesis that the data has the same kurtosis as a normal distribution.

Now let’s visualise these three tests for the normal distributions.

df_normal_data <- data.frame(normal_data = normal_data)

ggplot(data = df_normal_data, aes(x = normal_data)) +
  geom_histogram(aes(y = ..density..), bins = 10, fill = "skyblue", color = "black") +
  geom_density(color = "blue", linewidth = 1) +
  stat_function(fun = dnorm, args = list(mean = mean(normal_data), sd = sd(normal_data)), color = "red", linewidth = 1, linetype = "dashed") +
  labs(title = "Histogram with Normal Curve Overlay",
       x = "Value", y = "Density") +
  theme_minimal()

ggplot(df_normal_data, aes(sample = normal_data)) +
  stat_qq() +
  stat_qq_line(color = "red", linetype = "dashed") +
  labs(title = "Q-Q Plot for Normality",
       x = "Theoretical Quantiles", y = "Sample Quantiles") +
  theme_minimal()

Lewis, Nancy D., Nigel Da Costa Lewis, and N. D. Lewis. 2013. 100 Statistical Tests in r: What to Choose, How to Easily Calculate, with over 300 Illustrations and Examples. Heather Hills Press.
LS0tCnRpdGxlOiAiMTAwX1N0YXRpc3RpY2FsX1Rlc3RzX2luX1IiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICB0b2M6IHRydWUKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICBkZl9wcmludDogcGFnZWQKYmlibGlvZ3JhcGh5OiByZWZlcmVuY2VzLmJpYgplZGl0b3Jfb3B0aW9uczoKICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lCi0tLQoKIyAxMDAgU3RhdGlzdGljYWwgVGVzdHMgaW4gUiBOb3RlYm9vawoKVGhpcyBpcyB0aGUgUiBOb3RlYm9vayBmb3IgdGhlIEJvb2sgKjEwMCBTdGF0aXN0aWNhbCBUZXN0cyBpbiBSKiBmcm9tIFtAbGV3aXMxMDBTdGF0aXN0aWNhbFRlc3RzMjAxM10uCgpJbiBvcmRlciB0byBiZXR0ZXIgaWxsdXN0cmF0ZSB0aGUgc3RhdGlzdGljYWwgdGVzdHMgdGhyb3VnaCByZWFsLXdvcmxkIGFwcGxpY2F0aW9ucywgdGhpcyBub3RlYm9vayB3aWxsIHVzZSB0aGUgYnVpbHQtaW4gUiBkYXRhc2V0cyB0byBjb3ZlciBhbGwgdGVzdCB0eXBlcy4gUnVuIHRoZSBmb2xsb3dpbmcgY29kZXMgdG8gZW5zdXJlIGFsbCBwYWNrYWdlcyBhbmQgZGF0YXNldHMgYXJlIHByZXBhcmVkLgoKYGBge3IgUiBwYWNrYWdlIHByZXBhcmF0aW9uLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KHBzeWNoKQojIExvYWQgY29yZSBkYXRhc2V0cwpkYXRhKGlyaXMpCmRhdGEobXRjYXJzKQpkYXRhKGFpcnF1YWxpdHkpCmRhdGEoc2xlZXApCmRhdGEoVUNCQWRtaXNzaW9ucykKZGF0YShmYWl0aGZ1bCkKZGF0YShBaXJQYXNzZW5nZXJzKQoKIyBGb3Igc3Vydml2YWwgYW5hbHlzaXMKbGlicmFyeShsYXR0aWNlKQpsaWJyYXJ5KHN1cnZpdmFsKQpkYXRhKGx1bmcpCgojIEZvciBjaXJjdWxhciBzdGF0aXN0aWNzCmxpYnJhcnkoY2lyY3VsYXIpCmRhdGEod2luZCkKCiMgRm9yIHZpc3VhbGlzYXRpb24KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCgojIyMgVGVzdCAxIFBlYXJzb24ncyBwcm9kdWN0IG1vbWVudCBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBULXRlc3QKClRvIGFzc2VzcyB0aGUgbnVsbCBoeXBvdGhlc2lzIG9mIHplcm8gY29ycmVsYXRpb24gYmV0d2VlbiB0d28gdmFyaWFibGVzLiBXaGVuIHRvIHVzZSB0aGlzIHRlc3Q/CgotICAgSW50ZXJ2YWwgb3IgcmF0aW8gc2NhbGUKCi0gICBObyBuZWVkIGZvciBzYW1lIHNjYWxlCgotICAgQSBwYWlyZWQgc2FtcGxlIHdpdGggYXBwcm94aW1hdGVseSBub3JtYWxseSBkaXN0cmlidXRlZAoKLSAgIEpvaW50IGRpc3RyaWJ1dGlvbiBpcyBiaXZhcmlhdGUgbm9ybWFsCgotICAgTGluZWFyIHJlbGF0aW9uc2hpcHMKCkluIHRoaXMgdGVzdCwgd2Ugd2lsbCB1c2UgaXJpcyBkYXRhc2V0IHRvIGNvbXBhcmUgYW5kIGlsbHVzdHJhdGUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGxlbmd0aHMgb2Ygc2VwYWxzIGFuZCBwZXRhbHMuCgpgYGB7ciBJcmlzIERhdGFzZXQsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnN0cihpcmlzKQpzdW1tYXJ5KGlyaXMpCnN1bW1hcnkoaXJpcyRTZXBhbC5MZW5ndGgpCnN1bW1hcnkoaXJpcyRQZXRhbC5MZW5ndGgpCmBgYAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KY29yLnRlc3QoaXJpcyRTZXBhbC5MZW5ndGgsaXJpcyRQZXRhbC5MZW5ndGgsIG1ldGhvZCA9ICJwZWFyc29uIiwgYWx0ZXJhbnRpdmUgPSAidHdvLnNpZGVkIiwgY29uZi5sZXZlbCA9IDAuOTUpCmBgYAoKVGhlIGNvcnJlbGF0aW9uIGJldHdlZW4geCAobGVuZ3RoIG9mIHNlcGFscykgYW5kIHkgKGxlbmd0aCBvZiBwZXRhbCkgaXMgMC44NzIuIFRoZSBwLXZhbHVlIGlzIHNtYWxsZXIgdGhhbiAwLjA1LCB3ZSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyBvZiB6ZXJvIGNvcnJlbGF0aW9uLiA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbCBpcyByZXBvcnRlZCBiZXR3ZXduIFswLjgyNywwLjkwNl0sIHdoaWNoIGRvZXMgbm90IGNyb3NzIHplcm8uCgpgYGB7cn0KcGxvdChpcmlzJFNlcGFsLkxlbmd0aCxpcmlzJFBldGFsLkxlbmd0aCkKCmNvcl90ZXN0X2lyaXNfU2VwYWxfUGV0YWxfbGVuZ3RoIDwtIGdncGxvdChkYXRhID0gaXJpcywgYWVzKHg9U2VwYWwuTGVuZ3RoLCB5PVBldGFsLkxlbmd0aCkpICsgCiAgZ2VvbV9wb2ludCgpCgpjb3JfdGVzdF9pcmlzX1NlcGFsX1BldGFsX2xlbmd0aApgYGAKCiMjIyBUZXN0IDIgU3BlYXJtYW4gUmFuayBDb3JyZWxhdGlvbiBUZXN0CgpXaGVuIHRvIHVzZSB0aGlzIHRlc3Q/CgotICAgVG8gYXNzZXNzIHRoZSBudWxsIGh5cG90aGVzaXMgb2YgemVybyBjb3JyZWxhdGlvbiBiZXR3ZWVuIHR3byB2YXJpYWJsZXMuCgotICAgT3JkaW5hbCBvciByYW5rZWQgZGF0YQoKLSAgIERhdGEgaXMgY29udGludW91cyBhbmQgdW5yZWFzb25hYmxlIHRvIGFzc3VtZSB0aGUgdmFyaWFibGVzIGFyZSBub3JtYWxseSBkaXN0cmlidXRlZAoKLSAgIExpbmVhciByZWxhdGlvbnNoaXAKCkluIHRoaXMgdGVzdCwgd2Ugd2lsbCBjb250aW51ZSB0byB1c2UgaXJpcyBkYXRhc2V0IHRvIGNvbXBhcmUgYW5kIGlsbHVzdHJhdGUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGxlbmd0aHMgb2Ygc2VwYWxzIGFuZCBwZXRhbHMuCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpjb3IudGVzdChpcmlzJFNlcGFsLkxlbmd0aCxpcmlzJFBldGFsLkxlbmd0aCwgbWV0aG9kID0gInNwZWFybWFuIiwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikKYGBgCgpUaGUgY29ycmVsYXRpb24gYmV0d2VlbiB4IChsZW5ndGggb2Ygc2VwYWxzKSBhbmQgeSAobGVuZ3RoIG9mIHBldGFsKSBpcyAwLjg4Mi4gVGhlIHAtdmFsdWUgaXMgc21hbGxlciB0aGFuIDAuMDUsIHdlIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIG9mIHplcm8gY29ycmVsYXRpb24uIEluIHRoZSBzcGVhcm1hbiB0ZXN0LCB0aGVyZSBpcyBubyBjb25maWRlbmNlIGludGVydmFsIG5vcm1hbGx5LiBTcGVhcm1hbiBjb3JyZWxhdGlvbiB1c2VzIHJhbmstYmFzZWQgY2FsY3VsYXRpb25zIHJhdGhlciB0aGFuIHRoZSByYXcgZGF0YSB2YWx1ZXMsIG1ha2luZyB0aGUgc2FtcGxpbmcgZGlzdHJpYnV0aW9uIG1vcmUgY29tcGxleCBmb3IgY29tcHV0aW5nIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIHVzaW5nIHN0YW5kYXJkIHBhcmFtZXRyaXggbWV0aG9kcy4KCiMjIyBUZXN0IDMgS2VuZGFsbCdzIFRhdSBDb3JyZWxhdGlvbiBDb2VmZmljaWVudCBUZXN0CgpXaGVuIHRvIHVzZSB0aGlzIHRlc3Q/CgotICAgYSBwYWlyZWQgcmFuZG9tIHNhbXBsZSBvZiBvcmRpbmFsIG9yIHJhbmtlZCBkYXRhCgotICAgZGF0YSBpcyBjb250aW51b3VzIGFuZCBpdCBpcyB1bnJlYXNvbmFibGUgdG8gdGhlIHZhcmlhYmxlcyBhcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQKCi0gICBsaW5lYXIgcmVsYXRpb25zaGlwCgpXZSB3aWxsIHVzZSBhIG5ldyBkYXRhc2V0IG10Y2FycyB0byBpbGx1c3RyYXRlIHRoZSBUYXUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgdGVzdDoKCnwgICAgICAgfCAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwtLS0tLS0tfC0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18CnwgWywgMV0gfCBtcGcgIHwgTWlsZXMvKFVTKSBnYWxsb24gICAgICAgICAgICAgICAgICAgICAgICB8CnwgWywgMl0gfCBjeWwgIHwgTnVtYmVyIG9mIGN5bGluZGVycyAgICAgICAgICAgICAgICAgICAgICB8CnwgWywgM10gfCBkaXNwIHwgRGlzcGxhY2VtZW50IChjdS5pbi4pICAgICAgICAgICAgICAgICAgICB8CnwgWywgNF0gfCBocCAgIHwgR3Jvc3MgaG9yc2Vwb3dlciAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgWywgNV0gfCBkcmF0IHwgUmVhciBheGxlIHJhdGlvICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgWywgNl0gfCB3dCAgIHwgV2VpZ2h0ICgxMDAwIGxicykgICAgICAgICAgICAgICAgICAgICAgICB8CnwgWywgN10gfCBxc2VjIHwgMS80IG1pbGUgdGltZSAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgWywgOF0gfCB2cyAgIHwgRW5naW5lICgwID0gVi1zaGFwZWQsIDEgPSBzdHJhaWdodCkgICAgICB8CnwgWywgOV0gfCBhbSAgIHwgVHJhbnNtaXNzaW9uICgwID0gYXV0b21hdGljLCAxID0gbWFudWFsKSB8CnwgWywxMF0gfCBnZWFyIHwgTnVtYmVyIG9mIGZvcndhcmQgZ2VhcnMgICAgICAgICAgICAgICAgICB8CgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpzdHIobXRjYXJzKQpzdW1tYXJ5KG10Y2FycykKYGBgCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpjb3IudGVzdChtdGNhcnMkaHAsbXRjYXJzJHd0LCBtZXRob2Q9ImtlbmRhbCIsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpCmBgYAoKVGhlIGNvcnJlbGF0aW9uIGJldHdlZW4geCAoaHApIGFuZCB5ICh3dCkgaXMgMC42MTEuIFRoZSBwLXZhbHVlIGlzIHNpZ25pZmljYW50IHNtYWxsZXIgdGhhbiB0aGUgY3JpdGljYWwgdmFsdWUgMC4wNS4gVGhlcmVmb3JlLCB3ZSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4KCiMjIyBUZXN0IDQgWi1UZXN0IG9mIHRoZSBEaWZmZXJlbmNlIEJldHdlZW4gSW5kZXBlbmRlbnQgQ29ycmVsYXRpb25zCgpXaGVuIHRvIHVzZSB0aGlzIHRlc3Q/CgotICAgY29ycmVsYXRpb24gY29lZmZpY2llbnRzIGNhbGN1bGF0ZWQgZnJvbSBpbmRlcGVuZGVudCBzYW1wbGVzCgotICAgZGF0YSBhcmUgYXNzdW1lZCB0byBiZSBiaXZhcmlhdGUgbm9ybWFsCgotICAgc2FtcGxlIHNpemUgbWF5IGJlIGRpZmZlcmVudAoKWi10ZXN0IGlzIGxlc3MgY29tbW9uIHRoYW4gUGVhcnNvbiBvciBTcGVhcm1hbiBjb3JyZWxhdGlvbi4gSXQgYWN0dWFsbHkgZXhhbWluZXMgd2hldGhlciB0aGUgY29ycmVsYXRpb24gY29lZmZpY2llbnRzIGZyb20gdHdvIG9yIG1vcmUgc2FtcGxlcyB3aXRoIGRpZmZlcmVudCBzYW1wbGUgc2l6ZSBpcyBjb3JyZWxhdGVkIG9yIG5vdC4KCkluIHRoaXMgdGVzdCwgd2Ugd2lsbCB1c2UgaXJpcyBkYXRhc2V0IGFzIHRoZSBleGFtcGxlLiBXZSB3aWxsIGZpcnN0IGNhbGN1bGF0ZSB0aGUgY29ycmVsYXRpb24gY29lZmZpY2llbnRzIG9mIFNlcGFsIGxlbmd0aCBhbmQgUGV0YWwgbGVuZ3RoIGZyb20gZGlmZmVyZW50IHNwZWNpZXMuIEFmdGVyIHRoYXQsIHdlIHdpbGwgZXhhbWluZSB0aGUgWi10ZXN0IGJldHdlZW4gdGhlc2UgY29ycmVsYXRpb24gY29lZmZpY2llbnRzLiBXZSBhbHNvIG5lZWQgJ3BzeWNoJyBwYWNrYWdlIHRvIHVzZSBwYXJpZWQuciBmdW5jdGlvbi4gVGhpcyBmdW5jdGlvbiByZXF1aXJlIHNpeCBwYXJhbWV0ZXJzOiBjb3JyZWxhdGlvbiBjb2VmZmljaWVudHMgeHksIGNvcnJlbGF0aW9uIGNvZWVmZmljaWVudHMgeHosIGNvcnJlbGFpdG9uIHl6ID0gTlVMTCwgbnVtYmVyIGluIGZpcnN0IGdyb3VwLCBudW1iZXIgaW4gc2Vjb25kIGdyb3VwLCB0d290YWlsZWQKCmBgYHtyfQpjb3Jfc2V0b3NhIDwtIGNvcihpcmlzJFNlcGFsLkxlbmd0aFtpcmlzJFNwZWNpZXMgPT0gInNldG9zYSJdLCBpcmlzJFBldGFsLkxlbmd0aFtpcmlzJFNwZWNpZXMgPT0gInNldG9zYSJdLCBtZXRob2QgPSAicGVhcnNvbiIpCmNvcl92ZXJzaWNvbG9yIDwtIGNvcihpcmlzJFNlcGFsLldpZHRoW2lyaXMkU3BlY2llcyA9PSAidmVyc2ljb2xvciJdLCBpcmlzJFBldGFsLldpZHRoW2lyaXMkU3BlY2llcyA9PSAidmVyc2ljb2xvciJdLCBtZXRob2QgPSAicGVhcnNvbiIpCm5fc2V0b3NhIDwtIHN1bShpcmlzJFNwZWNpZXMgPT0gInNldG9zYSIpCm5fdmVyc2ljb2xvciA8LSBzdW0oaXJpcyRTcGVjaWVzID09ICJ2ZXJzaWNvbG9yIikKYGBgCgpOb3cgd2Ugd2lsbCB1c2UgcGFpcmVkLnIoKSB0byBjYWxjdWxhdGUgdGhlIFotdGVzdC4KCmBgYHtyfQp6X3Rlc3RfY29yX3NldG9zYV92ZXJzaWNvbG9yIDwtIHBhaXJlZC5yKGNvcl9zZXRvc2EsIGNvcl92ZXJzaWNvbG9yLCBOVUxMLCBuX3NldG9zYSwgbl92ZXJzaWNvbG9yLCB0d290YWlsZWQ9VFJVRSkKel90ZXN0X2Nvcl9zZXRvc2FfdmVyc2ljb2xvciR0ZXN0CnpfdGVzdF9jb3Jfc2V0b3NhX3ZlcnNpY29sb3Ikegp6X3Rlc3RfY29yX3NldG9zYV92ZXJzaWNvbG9yJHAKYGBgCgpUaGUgcC12YWx1ZSBpcyBsZXNzIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlIDAuMDUuIFRoZXJlZm9yZSB3ZSBjYW4gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMuCgojIyMgVGVzdCA1IERpZmZlcmVuY2UgQmV0d2VlbiBUd28gT3ZlcmxhcHBpbmcgQ29ycmVsYXRpb24gQ29lZmZpY2llbnRzCgpXaGVuIHRvIHVzZSB0aGlzIHRlc3Q/CgotICAgQ29tcGFyZSB0aGUgbnVsbCBoeXBvdGhlc2lzIG9mIHplcm8gY29ycmVsYXRpb24gYmV0d2VlbiBvbmUgcGFpciBvZiB2YXJpYWJsZXMgYW5kIGFub3RoZXIgcGFpciBvZiB2YXJpYWJsZXMgc2hhcmVkIHdpdGggYW4gb3ZlcmxhcHBpbmcgdmFyaWFibGUKCi0gICBhaW0gdG8gc2VsZWN0IHRoZSBiZXR0ZXIgaW5kaWNhdG9yIG9mIHR3byBhdmFpbGFibGUgcHJlZGljdG9ycyAoeCBhbmQgeSkgZm9yIGEgZGVwZW5kZW50IHZhcmlhYmxlIHoKCi0gICBkYXRhIGFyZSBhc3N1bWVkIHRvIGJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkCgotICAgcmVmZXJyZWQgdG8gYXMgU3RlaWdlcidzIHQtdGVzdCwgTWVuZydzIHQtdGVzdCwgUm9zZW50aGFsICYgUnViaW4ncyB0LXRlc3Qgb3IgV2lsbGlhbXMgdGVzdAoKV2Ugd2lsbCB1c2UgbXRjYXJzIHRvIGV2YWx1YXRlIHRoZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gdGhlIGNvcnJlbGF0aW9uIG9mIHd0ICh3ZWlnaHRzKSBhbmQgbXBnIChtaWxlcyBwZXIgZ2FsbG9uKSBhbmQgdGhlIGNvcnJlbGF0aW9uIG9mIGhwIChob3JzZXBvd2VyKSBhbmQgbXBnIGFuZCBmaWd1cmUgb3V0IHdoZXRoZXIgd3Qgb3IgaHAgaXMgYSBiZXR0ZXIgaW5kaWNhdG9yIG9mIG1wZy4KCldlIHdpbGwgbmVlZCBjb21wT3ZlcmxhcENvcnIgYW5kIHBzeWNoIHBhY2thZ2VzIGZvciB0aGlzIHRlc3QuCgpgYGB7cn0KbGlicmFyeShjb21wT3ZlcmxhcENvcnIpCmxpYnJhcnkocHN5Y2gpCmBgYAoKYGBge3J9CmNvcl9tcGdfd3QgPC0gY29yKG10Y2FycyRtcGcsbXRjYXJzJHd0LCBtZXRob2QgPSAicGVhcnNvbiIpCmNvcl9tcGdfaHAgPC0gY29yKG10Y2FycyRtcGcsIG10Y2FycyRocCwgbWV0aG9kID0gInBlYXJzb24iKQpjb3JfaHBfd3QgPC0gY29yKG10Y2FycyRocCwgbXRjYXJzJHd0LCBtZXRob2QgPSAicGVhcnNvbiIpCmNvbXBPdmVybGFwQ29ycihsZW5ndGgobXRjYXJzJG1wZyksIGNvcl9tcGdfd3QsIGNvcl9tcGdfaHAsIGNvcl9ocF93dCkKYGBgCgpUaGUgZmlyc3QgbnVtYmVyIGlzIHRoZSByZXN1bHQgb2YgdC10ZXN0IGFuZCB0aGUgc2Vjb25kIG51bWJlciBpcyBwLXZhbHVlLiBUaGUgcC12YWx1ZSBpcyBncmVhdGVyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlIDAuMDUuIFRoZXJlZm9yZSwgd2UgY2FuIG5vdCByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4KCldlIGNhbiBhbHNvIHVzZSBwc3ljaCBwYWNrYWdlIHRvIGNhbGN1bGF0ZSB0aGlzIGNvcnJlbGF0aW9uLgoKYGBge3J9CnBhaXJlZC5yKGNvcl9tcGdfd3QsIGNvcl9tcGdfaHAsIGNvcl9ocF93dCwgbGVuZ3RoKG10Y2FycyRtcGcpLCB0d290YWlsZWQgPSBUUlVFKQpgYGAKCldlIGNhbiBzZWUgdGhlIHNhbWUgcmVzdWx0cyBmcm9tIGJvdGggdHdvIHBhY2thZ2VzLiBBcyB0aGUgcGFja2FnZSB7Y29tcE92ZXJsYXBDb3JyfSBpcyBubyBsb25nZXIgbWFpbnRhaW5lZCwgd2Ugc2hvdWxkIHVzZSB7cHN5Y2h9IHRvIG1lYXN1cmUgdGhpcyB0ZXN0LgoKIyMjIFRlc3QgNiBEaWZmZXJlbmNlIEJldHdlZW4gVHdvIE5vbi1PdmVybGFwcGluZyBEZXBlbmRlbnQgQ29ycmVsYXRpb24gQ29lZmZpY2llbnRzCgpRdWVzdGlvbiB0byB0aGUgdGVzdCBhZGRyZXNzZXM6CgoqKklzIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHR3byB2YXJpYWJsZXMgKEEgYW5kIEIpIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gdHdvIG90aGVyIHZhcmlhYmxlcyAoQyBhbmQgRCksIHdoZW4gYWxsIGZvdXIgdmFyaWFibGVzIHdlcmUgbWVhc3VyZWQgaW4gdGhlIHNhbWUgZ3JvdXAuKioKCldoZW4gdG8gdXNlIHRoaXMgdGVzdD8KCi0gICBUbyBhc3Nlc3MgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBvbmUgcGFpciBvZiB2YXJpYWJsZXMgYW5kIGEgc2Vjb25kIG5vbi1vdmVybGFwcGluZyBwYWlyIG9mIHZhcmlhYmxlcy4KCi0gICBOb24tb3ZlcmxhcHBpbmcgY291bGQgYmUgcmVsYXRlZCBpdGVtcyBpbiBkaWZmZXJlbnQgdGltZXMKCi0gICBEYXRhIGFyZSBhc3N1bWVkIHRvIGJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkCgpVc3VhbGx5LCB0aGlzIG1ldGhvZCBhaW1zIHRvIGRpc2N1c3MgdGhlIGRpZmZlcmVuY2UgaW4gY29ycmVsYXRpb24gYmV0d2VlbiB0d28gdmFyaWFibGVzIGluIHR3byBkaWZmZXJlbnQgdGltZXMgZm9yIHNlcmlhbCBhbmFseXNpcy4gSGVyZSwgd2Ugd2lsbCBkaXNjdXNzIHRoZSBiYXNpYyBtb2RlIG9mIHRoaXMgdGVzdCwgdHdvIGluZGVwZW5kZW50IHNldHMgb2YgdmFyaWFibGVzIGluIHRoZSBkYXRhc2V0IG10Y2Fycy4KCkZvciB0aGUgY2FycyBpbiB0aGlzIGRhdGFzZXQsIGlzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBlbmdpbmUgcG93ZXIgKGhwIGFuZCBkaXNwKSBzaWduaWZpY2FudGx5IGRpZmZlcmVudCB3aXRoIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBwZXJmb3JtYW5jZSAobXBnIGFuZCB3dCkKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoInBzeWNoIikKYGBgCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpjb3JfaHBfZGlzcCA8LSBjb3IobXRjYXJzJGhwLCBtdGNhcnMkZGlzcCwgbWV0aG9kID0gInBlYXJzb24iKQpjb3JfbXBnX3d0IDwtIGNvcihtdGNhcnMkbXBnLCBtdGNhcnMkd3QsIG1ldGhvZCA9InBlYXJzb24iKQojd2UgYWxzbyBuZWVkIHRoZSBjcm9zcyByZWxhdGlvbnNoaXBzIGJldHdlZW4gdGhlc2UgdmFyaWFibGVzCgpjb3JfaHBfd3QgPC0gY29yKG10Y2FycyRocCwgbXRjYXJzJHd0LCBtZXRob2QgPSAicGVhcnNvbiIpCmNvcl9tcGdfZGlzcCA8LSBjb3IobXRjYXJzJG1wZywgbXRjYXJzJGRpc3AsIG1ldGhvZCA9ICJwZWFyc29uIikKY29yX21wZ19ocCA8LSBjb3IobXRjYXJzJG1wZywgbXRjYXJzJGhwLCBtZXRob2QgPSAicGVhcnNvbiIpCmNvcl9kaXNwX3d0IDwtIGNvcihtdGNhcnMkZGlzcCwgbXRjYXJzJHd0LCBtZXRob2QgPSAicGVhcnNvbiIpCnIudGVzdChsZW5ndGgobXRjYXJzJG1wZyksIHIxMiA9IGNvcl9ocF93dCxyMzQgPSAgY29yX21wZ193dCxyMjMgPSBjb3JfbXBnX2Rpc3AsIHIxMyA9IGNvcl9ocF93dCwgcjE0ID0gY29yX2hwX3d0LCByMjQgPSBjb3JfbXBnX2Rpc3AsIHR3b3RhaWxlZCA9IFRSVUUpCmBgYAoKV2UgY2FuIHNlZSB0aGUgcC12YWx1ZSBpcyAwLCBzbWFsbGVyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlIDAuMDUuIFRoZXJlZm9yZSwgd2UgY2FuIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzLiBUaGUgY29ycmVsYXRpb24gYmV0d2VlbiBlbmdpbmUgcG93ZXJzIGFuZCBjb3JyZWxhdGlvbiBiZXR3ZWVuIHBvd2VyIHBlcmZvcm1hbmNlIGFyZSBkaWZmZXJlbnQuCgojIyMgVGVzdCA3IEJhcnRsZXR0J3MgVGVzdCBvZiBTcGhlcmljaXR5CgpRdWVzdGlvbiB0byB0aGUgdGVzdCBhZGRyZXNzZXM6CgoqKkFyZSB0aGVzZSB2YXJpYWJsZXMgZXNzZW50aWFsbHkgaW5kZXBlbmRlbnQgb2YgZWFjaCBvdGhlcj8qKgoKV2hlbiB0byB1c2UgdGhpcyB0ZXN0PwoKLSAgIGNoZWNrIHRoZSBjb3JyZWxhdGlvbiBtYXRyaXggaXMgZGlmZmVyZW50IGZyb20gaWRlbnRpdHkgbWF0cml4CgotICAgaWRlbnRpdHkgbWF0cml4IG1lYW5zIGFsbCB2YXJpYWJsZXMgaW4gdGhpcyBtYXRyaXggYXJlIHVuY29ycmVsYXRlZAoKLSAgIHRvIGNoZWNrIHdoZXRoZXIgZGF0YSBpcyBzdWl0YWJsZSBmb3IgZmFjdG9yIGFuYWx5c2lzIChGQSkKCkZvciByZXNlYXJjaGVyLCBpZiB3ZSB3YW50IHRvIGNvbmR1Y3QgZmFjdG9yIGFuYWx5c2lzIGZvciBvdXIgdmFyaWFibGVzLCBpdCBpcyBpbXBvcnRhbnQgdGhhdCB3ZSBzaG91bGQgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgb2YgQmFydGxldHQncyB0ZXN0IHRoYXQgdGhlcmUgaXMgbm8gZGlmZmVyZW5jZSBiZXR3ZWVuIG91ciB2YXJpYWJsZSBtYXRyaXggYW5kIGlkZW50aXR5IG1hdHJpeC4gT25seSB3aGVuIHZhcmlhYmxlcyBhcmUgY29ycmVsYXRlZCB3aXRoIGVhY2ggb3RoZXIsIHdlIGNhbiBjb250aW51ZSB0byBkbyBmYWN0b3IgYW5hbHlzaXMuCgpGb3IgdGhpcyB0ZXN0LCB3ZSB3aWxsIHVzZSBpcmlzIGRhdGFzZXQgdG8gdGVzdCB0aGUgdmFyaWFibGUgbWF0cml4IGFtb25nIGBTZXBhbC5MZW5ndGhgLCBgU2VwYWwuV2lkdGhgLCBgUGV0YWwuTGVuZ3RoYCwgYFBldGFsLldpZHRoYC4KCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoInBzeWNoIikKYGBgCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQptYXRyaXhfZGF0YSA8LSBpcmlzWywgMTo0XQpjb3J0ZXN0LmJhcnRsZXR0KG1hdHJpeF9kYXRhKQpgYGAKCkFjY29yZGluZyB0byB0aGUgcmVzdWx0LCB3ZSBjYW4gZmluZCB0aGUgcC12YWx1ZSBpcyBzbWFsbGVyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlIDAuMDUuIFRoZXJlZm9yZSwgd2Ugc2hvdWxkIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgb3VyIG1hdHJpeCBpcyB0aGUgaWRlbnRpdHkgbWF0cml4LiBXZSBjYW4gYXJndWUgdGhhdCB0aGVyZSBhcmUgaW50ZXJuYWwgY29ycmVsYXRpb25zIGJldHdlZW4gb3VyIG1hdHJpeCBhbW9uZyBgU2VwYWwuTGVuZ3RoYCwgYFNlcGFsLFdpZHRoYCwgYFBldGFsLkxlbmd0aGAsIGFuZCBgUGV0YWwuV2lkdGhgLgoKIyMjIFRlc3QgOCBUaGUgSmVubnJpY2ggVGVzdCBvZiB0aGUgRXF1YWxpdHkgb2YgVHdvIE1hdHJpY2VzCgpRdWVzdGlvbiB0byB0aGUgdGVzdCBhZGRyZXNzZXM6CgoqKklzIHRoZSBmdW5kYW1lbnRhbCBwYXR0ZXJuIG9mIGNvcnJlbGF0aW9ucyBhdCBBIHRoZSBzYW1lIGFzIHRoZSBwYXR0ZXJuIGF0IEI/KioKClRvIHVzZSB0aGlzIHRlc3Q6CgotICAgVHdvIGluZGVwZW5kZW50IHNhbXBsZXMgb3Igc3Vic2FtcGxlcwoKLSAgIFRoZSBzYW1lIHNldCBvZiB2YXJpYWJsZXMgbWVhc3VyZWQgZm9yIGJvdGggZ3JvdXBzCgotICAgVGhlIGRhdGEgYXJlIGFzc3VtZWQgdG8gYmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQKCkluIHRoaXMgdGVzdCwgd2Ugd2lsbCB1c2UgdGhlIGBFdVN0b2NrTWFya2V0c2AgZGF0YXNldCwgd2hpY2ggaXMgYSBidWlsdC1pbiBkYXRhc2V0IGluIFIsIG1lYXN1cmluZyB0aGUgZGFpbHkgY2xvc2luZyBwcmljZXMgZm9yIDQgbWFqb3IgRVUgc3RvY2sgaW5kaWNlcyBmcm9tIDE5OTEtMTk5OC4KCldlIHdpbGwgZXhhbWluZSB0aGUgY29ycmVsYXRpb24gcGF0dGVybiBiZXR3ZWVuIHRoZSBEQVgsIFNNSSwgQ0FDLCBhbmQgRlRTRSBpbmRpY2VzIGRpZmZlcmVudCBpbiB0aGUgZmlyc3QgaGFsZiBvZiB0aGUgdGltZSBwZXJpb2QgYW5kIHRoZSBzZWNvbmQgaGFsZiBvZiB0aGUgdGltZSBwZXJpb2QuCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KCJwc3ljaCIpCnNhbXBsZTEgPC0gRXVTdG9ja01hcmtldHNbMTo5MDAsIF0Kc2FtcGxlMiA8LSBFdVN0b2NrTWFya2V0c1s5NjE6MTg2MCwgXQpgYGAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmNvcnRlc3QuamVubnJpY2goc2FtcGxlMSxzYW1wbGUyKQpgYGAKCkFjY29yZGluZyB0byB0aGUgcmVzdWx0LCB3ZSBjYW4gZmluZCB0aGUgcC12YWx1ZSBpcyBsYXJnZXIgdGhhbiB0aGUgY3JpdGljYWwgdmFsdWUgMC4wNS4gVGhlcmVmb3JlLCB3ZSBjYW4gbm90IHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlIGNvcnJlbGF0aW9uIHBhdHRlcm5zIG9mIHRoZXNlIHR3byBzYW1wbGVzIGFyZSBzdGF0aXN0aWNhbGx5IHRoZSBzYW1lLiBUaGUgb3ZlcmFsbCBwYXR0ZXJuIG9mIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIG1ham9yIEVVIHN0b2NrIGluZGljZXMgZGlkIG5vdCBzaWduaWZpY2FudGx5IGNoYW5nZSBiZXR3ZWVuIHRoZSB0d28gdGltZSBwZXJpb2RzLgoKIyMjIFRlc3QgOSBUaGUgR3JhbmdlciBDYXVzYWxpdHkgVGVzdAoKUXVlc3Rpb24gdG8gdGhlIHRlc3QgYWRkcmVzc2VzOgoKKipJcyBvbmUgdGltZSBzZXJpZXMgdXNlZnVsIGluIGZvcmVjYXN0aW5nIGFub3RoZXIgdGltZSBzZXJpZXM/KioKClRvIHVzZSB0aGlzIHRlc3Q6CgotICAgYXQgbGVhc3QgdHdvIHRpbWUgc2VyaWVzIGRhdGEKCi0gICBzdGF0aW9uYXJ5IGRhdGE6IGFsbCBwcm9wZXJ0aWVzIG9mIGRhdGEgYXJlIGNvbnN0YW50IG92ZXIgdGltZSBzdWNoIGFzIG1lYW4sIHZhcmlhbmNlIGFuZCBhdXRvY29ycmVsYXRpb24KCi0gICBkYXRhIGFyZSBhc3N1bWVkIHRvIGJlIG9yZGVyZWQgY2hyb25vbG9naWNhbGx5CgpJbiB0aGlzIHRlc3QsIHdlIHdpbGwgY29udGludWUgdG8gdXNlIHRoZSB0aW1lIHNlcmllcyBkYXRhIGBFdVN0b2NrTWFydGVyc2Agd2l0aCB0aGUgYGRpZmYoKWAgZnVuY3Rpb24gdG8gY3JlYXRlIGEgc3VpdGFibGUgZGF0YXNldCBmb3IgdGhpcyBhbmFseXNpcy4gV2Ugd2lsbCB0ZXN0IHRoZXNlIHJlbGF0aW9uc2hpcHM6CgotICAgRG9zZSBEQVggR3Jhbmdlci1jYXVzZSBDQUM/CgotICAgRG9lcyBEQVggR3Jhbmdlci1jYXVzZSBGVFNFPwoKLSAgIERvZXMgU01JIEdyYW5nZXItY2F1c2UgQ0FDPwoKLSAgIERvZXMgU01JIEdyYW5nZXItY2F1c2UgRlRTRT8KCmBgYHtyIERhdGEgUHJlcGFyYXRpb24sIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmRhdGEoIkV1U3RvY2tNYXJrZXRzIikKZGF4X2RpZmYgPC0gZGlmZihFdVN0b2NrTWFya2V0c1ssIkRBWCJdKQpzbWlfZGlmZiA8LSBkaWZmKEV1U3RvY2tNYXJrZXRzWywiU01JIl0pCmNhY19kaWZmIDwtIGRpZmYoRXVTdG9ja01hcmtldHNbLCJDQUMiXSkKZnRzZV9kaWZmIDwtIGRpZmYoRXVTdG9ja01hcmtldHNbLCJGVFNFIl0pCmBgYAoKYGBge3IgZ3JhbmdlciB0ZXN0IDEsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkobG10ZXN0KQpncmFuZ2VydGVzdChjYWNfZGlmZiB+IGRheF9kaWZmLCBvcmRlciA9IDMpCmBgYAoKQWNjb3JkaW5nIHRvIHRoZSByZXN1bHQsIHdlIGNhbiBmaW5kIHRoYXQgdGhlIHAtdmFsdWUgaXMgbGFyZ2VyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlIDAuMDUuVGhlcmVmb3JlLCB3ZSBjYW4gbm90IHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgREFYIGRvZXMgbm90IEdyYW5nZXItY2F1c2UgQ0FDLiBTaW1pbGFybHksIHdlIGNhbiBjb250aW51ZSB0byBmaW5pc2ggdGhlIHJlc3Qgb2YgdGVzdHMKCmBgYHtyIGdyYW5nZXIgdGVzdCAyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpncmFuZ2VydGVzdChmdHNlX2RpZmYgfiBkYXhfZGlmZiwgb3JkZXIgPSAzKQpncmFuZ2VydGVzdChjYWNfZGlmZiB+IHNtaV9kaWZmLCBvcmRlciA9IDMpCmdyYW5nZXJ0ZXN0KGZ0c2VfZGlmZiB+IHNtaV9kaWZmLCBvcmRlciA9IDMpCmBgYAoKQWNjb3JkaW5nIHRvIHRoZSB0ZXN0LCB3ZSBjYW4gc2VlIHRoYXQgdGhlIGxhdHRlciB0d28gcC12YWx1ZXMgYXJlIHNpZ25pZmljYW50IHNtYWxsZXIgdGhhbiB0aGUgY3JpdGljYWwgdmFsdWUgMC4wNS4gVGhlcmVmb3JlLCB3ZSBjYW4gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXNlcy4gU01JIEdyYW5nZXItY2F1c2VzIHRoZSBGVFNFIGFuZCBDQUMuCgpXZSBjYW4gYWxzbyB2aXN1YWxpc2UgdGhlc2UgcmVzdWx0cyB0byAic2VlIiB0aGUgcmVsYXRpb25zaGlwcy4gV2Ugd2lsbCB1c2UgZ2dwbG90IDIgYW5kIHpvbyBwYWNrYWdlcy4KCmBgYHtyIGdyYW5nZXIgdGVzdCB2aXN1YWxpc2F0aW9uLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoem9vKQoKcGxvdF9kYXRhIDwtIGRhdGEuZnJhbWUoCiAgRGF0ZSA9IDE6bGVuZ3RoKGRheF9kaWZmKSwKICBTTUkgPSBhcy5udW1lcmljKHNtaV9kaWZmKSwKICBDQUMgPSBhcy5udW1lcmljKGNhY19kaWZmKSwKICBGVFNFID0gYXMubnVtZXJpYyhmdHNlX2RpZmYpCikKCmdncGxvdChwbG90X2RhdGEsIGFlcyh4PURhdGUpKSArCiAgZ2VvbV9saW5lKGFlcyh5PVNNSSwgY29sb3IgPSAiU01JIikpICsKICBnZW9tX2xpbmUoYWVzKHk9Q0FDLCBjb2xvcj0iQ0FDIikpICsKICBsYWJzKHRpdGxlID0gIkRhaWx5IENoYW5nZXMgaW4gU01JIGFuZCBDQUMiLCB5ID0gIkNoYW5nZXMgaW4gUHJpY2UiLCB4PSJDaGFuZ2VzIGluIERheSIpICsKICB0aGVtZV9taW5pbWFsKCkKCmdncGxvdChwbG90X2RhdGEsIGFlcyh4PURhdGUpKSArCiAgZ2VvbV9saW5lKGFlcyh5PVNNSSwgY29sb3IgPSAiU01JIikpICsKICBnZW9tX2xpbmUoYWVzKHk9RlRTRSwgY29sb3I9IkZUU0UiKSkgKwogIGxhYnModGl0bGUgPSAiRGFpbHkgQ2hhbmdlcyBpbiBTTUkgYW5kIEZUU0UiLCB5ID0gIkNoYW5nZXMgaW4gUHJpY2UiLCB4PSJDaGFuZ2VzIGluIERheSIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgojIyMgVGVzdCAxMCBEdXJiaW4tV2F0c29uIEF1dG9jb3JyZWxhdGlvbiBUZXN0CgpRdWVzdGlvbiB0byB0aGUgdGVzdCBhZGRyZXNzZXM6CgoqKklzIHRoZXJlIHNlcmlhbCBjb3JyZWxhdGlvbiBpbiB0aGUgc2FtcGxlPyoqCgpUbyB1c2UgdGhpcyB0ZXN0OgoKLSAgIHdoZXRoZXIgcmVzaWR1YWxzIChlcnJvciB0ZXJtcykgZnJvbSBhIHJlZ3Jlc3Npb24gbW9kZWwgYXJlIGluZGVwZW5kZW50CgotICAgcmVzaWR1YWxzIGFyZSBzdGF0aW9uYXJ5IGFuZCBub3JtYWxseSBkaXN0cmlidXRpb24gd2l0aCB6ZXJvIG1lYW4KCklmIHJlc2lkdWFscyBhcmUgbm90IGluZGVwZW5kZW50LCB0aGUgbW9kZWwgd2lsbCBoYXZlIGluY29ycmVjdCBzdGFuZGFyZCBlcnJvcnMsIG1pc2xlYWRpbmcgcC12YWx1ZXMgYW5kIGZhbHNlIHBvc2l0aXZlcy4gVGhlIGVycm9yIGZyb20gb25lIG9ic2VydmF0aW9uIHByb3ZpZGVzIGluZm9ybWF0aW9uIGFib3V0IHRoZSBlcnJvciBpbiB0aGUgbmV4dCBvYnNlcnZhdGlvbiwgd2hpY2ggdmlvbGF0ZXMgdGhlIGFzc3VtcHRpb24gb2YgbGluZWFyIHJlZ3Jlc3Npb24uCgpGb3IgdGhpcyB0ZXN0LCB3ZSB3aWxsIHVzZSBgY2Fyc2AgdG8gYnVpbGQgYSBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwsIGFuZCB0ZXN0IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBgZGlzdCB+IHNwZWVkYC4KCmBgYHtyIER1cmJpbi1XYXRzb24gVGVzdCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZGF0YSgiY2FycyIpCgpjYXJfbW9kZWwgPC0gbG0oZGlzdCB+IHNwZWVkLCBkYXRhID0gY2FycykKYGBgCgpgYGB7ciBEdXJiaW4tV2F0c29uIFRlc3QgMSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeSgiY2FyIikKZHVyYmluV2F0c29uVGVzdChjYXJfbW9kZWwpCmBgYAoKQWNjb3JkaW5nIHRvIHRoZSByZXN1bHQsIHdlIGNhbiBzZWUgdGhhdCB0aGUgcC12YWx1ZSBpcyBsYXJnZXIgdGhhbiB0aGUgY3JpdGljYWwgdmFsdWUgMC4wNS4gVGhlcmVmb3JlLCB3ZSBjYW4gbm90IHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlcmUgaXMgbm8gYXV0b2NvcnJlbGF0aW9ucyBpbiB0aGlzIG1vZGVsLgoKVG8gdmlzdWFsaXNlIHRoZSByZXNpZHVhbHMsIHdlIGNhbiBwbG90IGVhY2ggcmVzaWR1YWwgYWdhaW5zdCB0aGUgb25lIHRoYXQgY2FtZSBiZWZvcmUgaXQgKHRoZSBsYWdnZWQgdmFsdWUpLiBJZiB0aGVyZSBpcyBubyBhdXRvY29ycmVsYXRpb24sIHdlIHNob3VsZCBzZWUgdGhlIHJhbmRvbSBkb3QgY2xvdWQgd2l0aCBubyBvYnNlcnZhYmxlIHBhdHRlcm4uCgpgYGB7ciBEdXJiaW4tV2F0c29uIHZpc3VhbGlzYXRpb24sIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnJlcyA8LSByZXNpZHVhbHMoY2FyX21vZGVsKQoKcmVzaWR1YWxfZGF0YSA8LSBkYXRhX2ZyYW1lKAogIFJlc2lkdWFscyA9IHJlc1stMV0sCiAgTGFnZ2VkX1Jlc2lkdWFscyA9IHJlc1stbGVuZ3RoKHJlcyldCikKCmdncGxvdChyZXNpZHVhbF9kYXRhLCBhZXMoeCA9IExhZ2dlZF9SZXNpZHVhbHMsIHk9IFJlc2lkdWFscykpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwKSArCiAgbGFicyh0aXRsZSA9ICJQbG90IG9mIHJlc2lkdWFscyBhbmQgbGFnZ2VkIHJlc2lkdWFscyIsIHggPSAibGFnZ2VkIHJlc2lkdWFscyIsIHkgPSAicmVzaWR1YWxzIikKYGBgCgojIyMgVGVzdCAxMSBCcmV1c2NoLUdvZGZyZXkgQXV0b2NvcnJlbGF0aW9uIFRlc3QKClF1ZXN0aW9uIHRvIHRoZSB0ZXN0IGFkZHJlc3NlczoKCioqSXMgdGhlcmUgc2VyaWFsIGNvcnJlbGF0aW9uIGluIHRoZSBzYW1wbGU/KioKClRvIHVzZSB0aGlzIHRlc3Q6CgotICAgaW5jbHVkZWQgbGFnZ2VkIHZhbHVlcyBpbiB0aGUgbW9kZWwKCi0gICByZXNpZHVhbHMgYXJlIGFzc3VtZWQgdG8gYmUgc3RhdGlvbmFyeSBhbmQgbm9ybWFsbHkgZGlzdHJpYnV0aW9uIHdpdGggemVybyBtZWFuCgotICAgcG93ZXJmdWwgYW5kIGdlbmVyYWwgdGhhbiBEdXJiaW4tV2F0c29uIEF1dG9jb3JyZWxhdGlvbiB0ZXN0CgpUaGlzIHRlc3QgaXMgdXNlZCB3aGVuIHRoZXJlIGlzIGxhZ2dlZCB2YWx1ZXMgb2YgZGVwZW5kZW50IHZhcmlhYmxlcyBpbiB0aGUgbW9kZWwsIHdoaWNoIGNhbiBub3QgdXNlIHRoZSBEdXJiaW4tV2F0c29uIHRlc3QuIEZvciBleGFtcGxlLCB0aGUgZ3Jvd3RoIG9mIHBvcHVsYXRpb24gaW4gb25lIGNpdHkgb3IgdGhlIHN0b2NrIHByaWNlcyBpbiB0aGUgbWFya2V0LiBXZSB3aWxsIHVzZSBgRXVTdG9ja01hcmtldHNgIHRvIGV4YW1pbmUgdGhpcyB0ZXN0LiBXZSB3aWxsIGV4YW1pbmUgdGhlIGRhaWx5IGNoYW5nZXMgb2YgREFYLgoKYGBge3IgQkcgZGF0YSBwcmVwcmF0aW9uLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGxtdGVzdCkKZGF4X2RmIDwtIGRhdGEuZnJhbWUoREFYX2NoYW5nZSA9IGFzLm51bWVyaWMoZGF4X2RpZmYpKQoKZGF4X2RmIDwtIGRheF9kZiAlPiUKICBtdXRhdGUoREFYX2NoYW5nZV9sYWcxID0gbGFnKERBWF9jaGFuZ2UsIDEpKQoKZHluYW1pY19tb2RlbCA8LSBsbShEQVhfY2hhbmdlIH4gREFYX2NoYW5nZV9sYWcxLCBkYXRhID0gZGF4X2RmKQpgYGAKCmBgYHtyIEJHIHRlc3QgMSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KYmd0ZXN0KGR5bmFtaWNfbW9kZWwsIG9yZGVyID0gMykKYGBgCgpBY2NvcmRpbmcgdG8gdGhpcyByZXN1bHQsIHRoZSBwLXZhbHVlIGlzIGxhcmdlciB0aGFuIHRoZSBjcml0aWNhbCB2YWx1ZSAwLjA1LiBUaGVyZWZvcmUsIHdlIGNhbiBub3QgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCB0aGVyZSBpcyBubyBsYWdnZWQgdmFsdWUgaW4gdGhlIGRlcGVuZGVudCB2YXJpYWJsZXMuCgojIyBUZXN0IDEyIFQtdGVzdAoKIyMjIFRlc3QgMTIgT25lLVNhbXBsZSB0LXRlc3QgRm9yIGEgSHlwb3RoZXNpc2VkIE1lYW4KClF1ZXN0aW9uIHRvIHRoZSB0ZXN0IGFkZHJlc3NlczoKCioqSXMgdGhlIG1lYW4gb2YgYSBzYW1wbGUgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSBhIGh5cG90aGVzaXNlZCBtZWFuPyoqCgpUbyB1c2UgdGhpcyB0ZXN0OgoKLSAgIGRhdGEgaXMgYXNzdW1lZCB0byBiZSBub3JtYWxseSBkaXN0cmlidXRlZAoKLSAgIHRoZSBwb3B1bGF0aW9uIHN0YW5kYXJkIGRldmlhdGlvbiBpcyB1bmtub3duCgpGb3IgdGhpcyB0ZXN0LCB3ZSB3aWxsIHVzZSB0aGUgYnVpbHQtaW4gZGF0YXNldCBgc2xlZXBgLgoKYGBge3IgT25lIHNhbXBsZSB0LXRlc3QsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmRydWcxX2RhdGEgPC0gc2xlZXAgJT4lIAogIGZpbHRlcihncm91cCA9PSAxKQoKdC50ZXN0KGRydWcxX2RhdGEkZXh0cmEsIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikKYGBgCgpBY2NvcmRpbmcgdG8gdGhlIHJlc3VsdCwgd2UgY2FuIGZpbmQgdGhhdCB0aGUgcC12YWx1ZSBpcyBsYXJnZXIgdGhhbiB0aGUgY3JpdGljYWwgdmFsdWUgMC4wNS4gVGhlcmVmb3JlLCB3ZSBjYW4gbm90IHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlIGRydWcgaGFzIG5vIGVmZmVjdCBvbiBzbGVlcCBhdmVyYWdlIHRpbWUuCgojIyMgVGVzdCAxMzogT25lLXNhbXBsZSBXaWxjb3hvbiBTaWduZWQtUmFuayBUZXN0CgpRdWVzdGlvbiB0byB0aGUgdGVzdCBhZGRyZXNzZXM6CgoqKklzIHRoZSBtZWRpYW4gb2YgYSBzYW1wbGUgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSBhIGh5cG90aGVzaXNlZCB2YWx1ZT8qKgoKVG8gdXNlIHRoaXMgdGVzdDoKCi0gICBzYW1wbGUgZGF0YSBhcmUgYXNzdW1lZCBub3QgdG8gYmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQKCi0gICBhIG5vbnBhcmFtZXRyaWMgdGVzdAoKLSAgIGFsdGVybmF0aXZlIG1ldGhvZCB0byB0aGUgb25lLXNhbXBsZSB0LXRlc3QKClRoaXMgdGVzdCBpcyBjbG9zZWx5IHJlbGF0ZWQgdG8gdGhlIHRlc3QgMTIuIEluIG9yZGVyIHRvIHByYWN0aWNlIHRoaXMgdGVzdCwgd2UgZmlyc3QgZXhhbWluZSB0aGUgZGlzdHJpYnV0aW9uIG9mIHNhbXBsZSBkYXRhc2V0IHRoYXQgd2UgY3JlYXRlZC4KCmBgYHtyIDEzIGRpc3RpcmJ1dGlvbiAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnNoYXBpcm8udGVzdChkcnVnMV9kYXRhJGV4dHJhKQpgYGAKCkFjY29yZGluZyB0byB0aGUgcmVzdWx0LCB0aGUgcC12YWx1ZSBpcyBsYXJnZXIgdGhhbiB0aGUgY3JpdGljYWwgdmFsdWUgMC4wNS4gVGhlcmVmb3JlLCB3ZSBjYW4gbm90IHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlIHNhbXBsZSBkYXRhIGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLiBFdmVuIHRob3VnaCBvbmUtc2FtcGxlIHQtdGVzdCBpcyBiZXR0ZXIsIHdlIGNhbiBzdGlsbCB1c2UgdGhlIFdpbGNveG9uIHRlc3QgaGVyZS4KCmBgYHtyIDEzIHRlc3QsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CndpbGNveC50ZXN0KGRydWcxX2RhdGEkZXh0cmEsIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikKYGBgCgpBY2NvcmRpbmcgdG8gdGhlIHJlc3VsdCwgd2UgY2FuIGZpbmQgdGhhdCB0aGUgcC12YWx1ZSBpcyBsYXJnZXIgdGhhbiB0aGUgY3JpdGljYWwgdmFsdWUgMC4wNS4gVGhlcmVmb3JlLCB3ZSBjYW4gbm90IHJlamVjdCB0aGUgbnVsbC1oeXBvdGhlc2lzLiBXZSBnZXQgdGhlIHNhbWUgY29uY2x1c2lvbnMgZnJvbSB0LXRlc3QgYW5kIFdpbGNveG9uIHRlc3QuCgojIyMgVGVzdCAxNCBTaWduIFRlc3QgZm9yIGEgSHlwb3RoZXNpc2VkIE1lZGlhbgoKUXVlc3Rpb24gdG8gdGhlIHRlc3QgYWRkcmVzc2VzOgoKKipJcyB0aGUgbWVkaWFuIG9mIGEgc2FtcGxlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gYSBoeXBvdGhlc2lzZWQgbWVkaWFuPyoqCgpUbyB1c2UgdGhpcyB0ZXN0OgoKLSAgIG5vbnBhcmFtZXRyaWMgdGVzdAoKLSAgIGV2ZW4gc2ltcGxlciByZXF1aXJlbWVudHMgdGhhbiBXaWxjb3hvbiB0ZXN0CgotICAgYmVzdCBmb3IgZGVzY3JpcHRpb24gZGF0YSBsaWtlIGJldHRlciwgc2FtZSwgd29yc2UKCi0gICBsZXNzIHBvd2VyZnVsIHRoYW4gV2lsY294b24gdGVzdCBhbmQgdC10ZXN0CgpXZSB3aWxsIGNvbnRpbnVlIHRvIHVzZSB0aGUgZHJ1ZyBkYXRhIGFzIHNhbXBsZSB0byBkZW1vbnN0cmF0ZSB0aGUgY29kaW5nIHByb2Nlc3Nlcy4gV2Ugd2lsbCBuZWVkIHBhY2thZ2UgYEJTREFgIHRvIGNhbGN1bGF0ZSB0aGlzIHRlc3QuCgpgYGB7ciB0ZXN0IDE0LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KEJTREEpCgpTSUdOLnRlc3QoZHJ1ZzFfZGF0YSRleHRyYSwgbXU9MCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikKYGBgCgpBY2NvcmRpbmcgdG8gdGhlIHJlc3VsdHMsIHdlIGNhbiBmaW5kIHRoYXQgdGhlIHAtdmFsdWUgaXMgbGFyZ2VyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlIDAuMDUuIFRoZXJlZm9yZSwgd2UgY2FuIG5vdCByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4gQ29tcGFyZWQgdG8gdC10ZXN0IGFuZCBXaWxjb3hvbiB0ZXN0LCB3ZSBjYW4gZmluZCB0aGF0IHRoZSBzaW1wbGVyIGNvbmRpdGlvbnMgYSB0ZXN0IHJlcXVpcmVzLCB0aGUgbGFyZ2VyIHAtdmFsdWUgd2UgY2FuIGdldC4KCiMjIyBUZXN0IDE1IFR3by1zYW1wbGUgdC10ZXN0IGZvciB0aGUgRGlmZmVyZW5jZSBpbiBTYW1wbGUgTWVhbnMKClF1ZXN0aW9uIHRvIHRoZSB0ZXN0IGFkZHJlc3NlczoKCioqSXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbWVhbiBvZiB0d28gc2FtcGxlcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIHplcm8/KioKClRvIHVzZSB0aGlzIHRlc3Q6CgotICAgY29tcGFyZSBtZWFucyBvZiB0d28gaW5kZXBlbmRlbnQgZ3JvdXBzCgotICAgZWFjaCBncm91cCBpcyBhc3N1bWVkIHRvIGJlIG5vcm1hbGx5IGRpc3RyaWJ1dGlvbgoKLSAgIHZhcmlhbmNlcyBvZiB0d28gZ3JvdXBzIGFyZSBlcXVhbAoKSW4gdGhpcyB0ZXN0LCB3ZSB3aWxsIHVzZSB0aGUgYGNoaWNrd3RzYCBkYXRhc2V0IHdoaWNoIGNvbnRhaW5zIHRoZSB3ZWlnaHRzIG9mIDcxIHNpeC13ZWVrLW9sZCBjaGlja3MgZmVkIGJ5IGRpZmZlcmVudCB0eXBlcyBvZiBmZWVkLiBMZXQncyB0ZXN0IGlmIHRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBpbiB0aGUgZmluYWwgd2VpZ2h0IG9mIGNoaWNrcyBmZWQgYnkgIioqY2FzZWluKioiIGFuZCAiKipzb3liZWFuKioiCgpgYGB7ciB0ZXN0IDE1IGRhdGEgcHJlcGFyYXRpb24sIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmRhdGEoY2hpY2t3dHMpCmhlYWQoY2hpY2t3dHMpCgpjaGlja3NfY29tcGFyZSA8LSBjaGlja3d0cyAlPiUgCiAgZmlsdGVyKGZlZWQgJWluJSBjKCJjYXNlaW4iLCJzb3liZWFuIikpCmBgYAoKYGBge3IgdGVzdCAxNSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KdC50ZXN0KHdlaWdodCB+IGZlZWQsIGRhdGEgPSBjaGlja3NfY29tcGFyZSwgdmFyLmVxdWFsID0gVFJVRSkKYGBgCgpBY2NvcmRpbmcgdG8gdGhpcyByZXN1bHQsIHdlIGNhbiBmaW5kIHRoYXQgdGhlIHAtdmFsdWUgaXMgc21hbGxlciB0aGFuIHRoZSBjcml0aWNhbCB2YWx1ZSAwLjA1LiBUaGVyZWZvcmUsIHdlIGNhbiByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZXJlIGlzIG5vIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgd2VpZ2h0cyBmcm9tIHNveWJlYW4gZ3JvdXAgb2YgY2hpY2tzIGFuZCBjYXNlaW4gZ3JvdXAgb2YgY2hpY2tzLgoKIyMjIFRlc3QgMTYgUGFpcndpc2UgdC10ZXN0IGZvciB0aGUgRGlmZmVyZW5jZSBpbiBTYW1wbGUgTWVhbnMKClF1ZXN0aW9uIHRvIHRoZSB0ZXN0IGFkZHJlc3NlczoKCioqSXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbWVhbiBvZiB0aHJlZSBvciBtb3JlIHNhbXBsZXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSB6ZXJvPyoqCgpUbyB1c2UgdGhpcyB0ZXN0OgoKLSAgIG1vcmUgdGhhbiB0d28gZ3JvdXBzIG9mIGRhdGEKCi0gICBhbGwgZGF0YSBhcmUgYXNzdW1lZCB0byBiZSBub3JtYWxseSBkaXN0cmlidXRlZAoKV2Ugd2lsbCBjb250aW51ZSB1c2UgdGhlIGBjaGlja3d0c2AgZGF0YXNldC4gTm93IHdlIHdpbGwgY29tcGFyZSBhbGwgZGlmZmVyZW50IHR5cGVzIG9mIGZlZWQgYXQgdGhlIHNhbWUgdGltZS4gVGhlcmVmb3JlLCB3ZSBuZWVkIHRvIHVzZSB0aGUgYWRqdXN0IHAtdmFsdWUgZm9yIG1vcmUgYWNjdXJhdGUgcmVzdWx0cy4gV2Ugd2lsbCBhZGp1c3QgdGhlIGBwb29sLnNgZCB0byBGQUxTRSBmb3IgdGhlIGNvbXBhcmlzb24gZm9yIHRlc3QgMTcuIEhvd2V2ZXIsIHdlIG5lZWQgdG8gcmVtZW1iZXIgd2UgZG8gbm90IG5lZWQgdG8gc2V0IGBwb29sLnNkYCB0byBGQUxTRSBpbiBhY3R1YWwgdXNlcy4KCmBgYHtyIHRlc3QgMTYsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnBhaXJ3aXNlLnQudGVzdChjaGlja3d0cyR3ZWlnaHQsIGNoaWNrd3RzJGZlZWQsIHAuYWRqdXN0Lm1ldGhvZCA9ICJob2xtIiwgcG9vbC5zZCA9IEZBTFNFKQpgYGAKCkFjY29yZGluZyB0byB0aGUgcmVzdWx0cywgd2UgY2FuIGZpbmQgdGhhdCBzb21lIHAtdmFsdWVzIGFyZSB2YXJpZWQgaW4gdGhlIHRhYmxlLiBGb3IgZXhhbXBsZSwgd2UgY2FuIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2VzIG9mIGNhc2VpbiBhbmQgaG9yc2ViZWFtLCBhbmQgY2FzZWluIGFuZCBsaW5zZWVkIGJ1dCB3ZSBjYW4gbm90IHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2VzIG9mIGNhc2VpbiBhbmQgbWVhdG1lYWwsIGFuZCBjYXNlaW4gYW5kIHN1bmZsb3dlci4KClRoZSByZWFzb24gd2h5IHRoZSBwLXZhbHVlIG9mIHRoZSBwYWlyICJjYXNlaW4gYW5kIHNveWJlYW4iIGlzIGEgYml0IGxhcmdlciB0aGFuIHRoZSBleGFtcGxlIGluIHRlc3QgMTUgaXMgdGhhdCBwLXZhbHVlIGFkanVzdG1lbnQgZm9yIG11bHRpcGxlIGNvbXBhcmlzb25zLiBUaGUgImhvbG0iIG1ldGhvZCBzbGlnaHRseSBpbmNyZWFzZXMgdGhlIHAtdmFsdWVzIHRvIHJlZHVjZSB0aGUgY2hhbmNlIG9mIG1ha2luZyBUeXBlIEkgZXJyb3IuCgojIyMgVGVzdCAxNyBQYWlyd2lzZSB0LXRlc3Qgd2l0aCBDb21tb24gVmFyaWFuY2UKClF1ZXN0aW9uIHRvIHRoZSB0ZXN0IGFkZHJlc3NlczoKCioqSXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbWVhbiBvZiB0aHJlZSBvciBtb3JlIHNhbXBsZXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSB6ZXJvPyoqCgpUbyB1c2UgdGhpcyB0ZXN0OgoKLSAgIHZhcmlhbmNlcyBhcmUgZXF1YWwgYWNyb3NzIGFsbCB0ZXN0IGdyb3VwcwoKLSAgIHBvd2VyZnVsIHRoYW4gdGVzdCAxNiBpZiB0aGUgYXNzdW1wdGlvbiBpcyB0cnVlCgpUaGUgb25seSBjaGFuZ2UgZm9yIHRoaXMgdGVzdCBpcyB0aGF0IHdlIHNldCB0aGUgYHBvb2wuc2RgIHRvIFRSVUUuCgpgYGB7ciB0ZXN0IDE3LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwYWlyd2lzZS50LnRlc3QoY2hpY2t3dHMkd2VpZ2h0LCBjaGlja3d0cyRmZWVkLCBwLmFkanVzdC5tZXRob2QgPSAiaG9sbSIsIHBvb2wuc2QgPSBUUlVFKQpgYGAKCkFjY29yZGluZyB0byB0aGUgcmVzdWx0cywgd2UgYWxtb3N0IGdldCB0aGUgc2FtZSBhbnN3ZXJzIGZyb20gdGVzdCAxNSBhbmQgdGVzdCAxNi4gSG93ZXZlciwgc29tZSBjaGFuZ2VzIGFyZSBvYnNlcnZhYmxlLiBGb3IgZXhhbXBsZSwgdGhlIHAtdmFsdWUgYmV0d2VlbiBjYXNlaW4gYW5kIHNveWJlYW4gaXMgc2xpZ2h0bHkgbGFyZ2VyIHRoYW4gdGhlIHAtdmFsdWUgaW4gdGVzdCAxNSBidXQgc21hbGxlciB0aGFuIHRoZSBwLXZhbHVlIGluIHRlc3QgMTYgd2hlbiBgcG9vbC5zZGAgaXMgc2V0IHRvIEZBTFNFLgoKVGhlIHJlYXNvbiB3aHkgdGhyZWUgcC12YWx1ZXMgb2YgdGhlIHBhaXIgImNhc2VpbiBhbmQgc295YmVhbiBhcmUgZGlmZmVyZW50IGlzIHRoYXQgZGlmZmVyZW50IGtpbmRzIG9mIHZhcmlhbmNlcyBhcmUgdXNlZCBpbiB0aGUgY2FsY3VsYXRpb24uIEZvciB0ZXN0IDE1LCB3ZSBvbmx5IGNhbGN1bGF0ZSB0aGUgZGV2aWF0aW9uIGJldHdlZW4gImNhc2VpbiIgYW5kICJzb3liZWFuIi4gSW4gdGVzdCAxNywgd2UgYWN0dWFsbHkgdGVzdCB0aGUgZGV2aWF0aW9ucyBhY3Jvc3Mgc2l4IGdyb3VwcyB0b2dldGhlciwgd2hpY2ggY29udGFpbnMgbW9yZSBkYXRhLiBGb3IgdGhlIHRlc3QgMTYsIHdlIGNhbGN1bGF0ZSB0aGUgdGVzdCB0aHJvdWdoIGEgc2VwYXJhdGUgY29tcGFyaXNvbiBmb3IgZWFjaCBwYWlyIHdpdGhvdXQgYXNzdW1pbmcgZXF1YWwgdmFyaWFuY2VzLiBUaGlzIGlzIGFjdHVhbGx5IHRoZSBXZWxjaCB0LXRlc3QsIHdoaWNoIHdpbGwgYmUgZGlzY3Vzc2VkIGluIHRlc3QgMTguCgojIyMgVGVzdCAxOCBXZWxjaCB0LXRlc3QgZm9yIHRoZSBEaWZmZXJlbmNlIGluIFNhbXBsZSBNZWFucwoKUXVlc3Rpb24gdG8gdGhlIHRlc3QgYWRkcmVzc2VzOgoKKipJcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBtZWFuIG9mIHR3byBzYW1wbGUgZ3JvdXBzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gemVybz8qKgoKVG8gdXNlIHRoaXMgdGVzdDoKCi0gICBub3QgYXNzdW1lZCB0byBiZSBlcXVhbCB2YXJpYW5jZXMKClRoZSBjb2RlIGZvciB0aGlzIHRlc3QgaXMgYXMgc2FtZSBhcyB3aGF0IHdlIGRpZCBpbiAxNiBidXQgb25seSB3aXRoIHR3byBncm91cHMgb2YgZmVlZHMuCgpgYGB7ciB0ZXN0IDE4LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpmZWVkc190b19jb21wYXJlIDwtIGNoaWNrd3RzICU+JQogIGZpbHRlcihmZWVkICVpbiUgYygiY2FzZWluIiwgInNveWJlYW4iKSkKCnQudGVzdCh3ZWlnaHQgfiBmZWVkLCBkYXRhID0gZmVlZHNfdG9fY29tcGFyZSwgdmFyLmVxdWFsID0gRkFMU0UpCmBgYAoKQWNjb3JkaW5nIHRvIHRoZSByZXN1bHRzLCB3ZSBjYW4gZmluZCB0aGF0IHAtdmFsdWUgaXMgc21hbGxlciB0aGFuIHRoZSBjcml0aWNhbCB2YWx1ZSAwLjA1LiBUaGVyZWZvcmUsIHdlIGNhbiByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZXJlIGlzIG5vIGRpZmZlcmVuY2UgaW4gdGhlIGZpbmFsIHdlaWdodHMgb2YgY2hpY2tzIGJldHdlZW4gdHdvIHR5cGVzIG9mIGZlZWRzLgoKIyMjIFRlc3QgMTkgUGFpcmVkIHQtdGVzdCBmb3IgdGhlIERpZmZlcmVuY2UgaW4gU2FtcGxlIE1lYW5zCgpRdWVzdGlvbiB0byB0aGUgdGVzdCBhZGRyZXNzZXM6CgoqKklzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIG1lYW4gb2YgdHdvIHJlbGF0ZWQgc2FtcGxlcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIHplcm8/KioKClRvIHVzZSB0aGlzIHRlc3Q6CgotICAgbWVhc3VyZSBzYW1lIHN1YmplY3QgdHdpY2UsIGJlZm9yZSBhbmQgYWZ0ZXIKCi0gICBzdWJqZWN0cyBhcmUgYXNzdW1lZCB0byBiZSBkcmF3biBmcm9tIGEgcG9wdWxhdGlvbiB3aXRoIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbgoKV2Ugd2lsbCB1c2UgdGhlIGBzbGVlcGAgZGF0YXNldCB0byBleGFtaW5lIHRoZSBkcnVnIGVmZmVjdHMgb24gc2xlZXAgZHVyYXRpb24uCgpgYGB7ciB0ZXN0IDE5LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpkcnVnMV9zbGVlcCA8LSBzbGVlcCRleHRyYVtzbGVlcCRncm91cCA9PSAxXQoKZHJ1ZzJfc2xlZXAgPC0gc2xlZXAkZXh0cmFbc2xlZXAkZ3JvdXAgPT0gMl0KCnQudGVzdChkcnVnMV9zbGVlcCwgZHJ1ZzJfc2xlZXAsIHBhcmllZCA9IFRSVUUsIHZhci5lcXVhbCA9IFRSVUUpCmBgYAoKQWNjb3JkaW5nIHRvIHRoZSByZXN1bHRzLCB3ZSBmaW5kIHRoYXQgdGhlIHAtdmFsdWUgaXMgbGFyZ2VyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlIDAuMDUuIFRoZXJlZm9yZSwgd2UgY2FuIG5vdCByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZXJlIGlzIG5vIGRpZmZlcmVuY2Ugb24gdGhlIG1lYW4gZWZmZWN0IGJldHdlZW4gZHJ1ZyAxIGFuZCBkcnVnIDIgb24gdGhlIHNhbWUgcGVyc29uLgoKIyMjIFRlc3QgMjAgTWF0Y2hlZCBQYWlycyBXaWxjb3hvbiBUZXN0CgpRdWVzdGlvbiB0byB0aGUgdGVzdCBhZGRyZXNzZXM6CgoqKklzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIG1lYW4gb2YgdHdvIHJlbGF0ZWQgc2FtcGxlcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIHplcm8/KioKClRvIHVzZSB0aGlzIHRlc3Q6CgotICAgZGF0YSBhcmUgcGFpcmVkCgotICAgY2FuIG5vdCBhc3N1bWUgdGhlIGRpZmZlcmVuY2VzIGFyZSBub3JtYWxseSBkaXN0cmlidXRlZAoKLSAgIG9uIHJhbmtzIG9mIGRpZmZlcmVuY2VzCgpXZSB3aWxsIHN0aWxsIHVzZSB0aGUgYHNsZWVwYCBkYXRhc2V0IGluIHRoaXMgdGVzdC4KCmBgYHtyIHRlc3QgMjAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CndpbGNveC50ZXN0KGRydWcxX3NsZWVwLCBkcnVnMl9zbGVlcCwgcGFpcmVkID0gVFJVRSkKYGBgCgpBY2NvcmRpbmcgdG8gdGhlIHJlc3VsdCwgd2UgY2FuIGZpbmQgdGhhdCB0aGUgcC12YWx1ZSBpcyBzbWFsbGVyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlIDAuMDUuIFRoZXJlZm9yZSwgd2UgY2FuIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlcmUgaXMgbm8gZGlmZmVyZW5jZSBvbiB0aGUgZHJ1ZyBlZmZlY3RzIGJldHdlZW4gZHJ1ZyAxIGFuZCBkcnVnIDIgb24gdGhlIHNhbWUgcGVyc29uLgoKQ29tcGFyZWQgdG8gdGhlIHJlc3VsdCBpbiBUZXN0IDE5LCB3ZSBnZXQgdGhlIG9wcG9zaXRlIGNvbmNsdXNpb25zLiBUZXN0IDE5IGluZGljYXRlcyB0aGF0IHdlIGNhbiBub3QgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgYnV0IFRlc3QgMjAgaW5kaWNhdGVzIHRoYXQgd2UgY2FuIGRvIGl0LiBUaGUgc3RhdGlzdGljYWwgcmVhc29uIGlzIHRoYXQgdGhlIFdpbGNveG9uIHRlc3QgaXMgb2Z0ZW4gKiptb3JlIHBvd2VyZnVsKiogdGhhbiB0aGUgdC10ZXN0IHdoZW4gdGhlIGRhdGEgaXMgbm90IHBlcmZlY3RseSBub3JtYWxseSBkaXN0cmlidXRlZCBvciB3aGVuIHRoZXJlIGFyZSBvdXRsaWVycy4gVGhlIFdpbGNveG9uIHRlc3Qgd29ya3Mgd2l0aCB0aGUgcmFua3Mgb2YgdGhlIGRhdGEsIHdoaWNoIG1ha2VzIGl0IGxlc3Mgc2Vuc2l0aXZlIHRvIG9uZSBvciB0d28gdW51c3VhbGx5IGxhcmdlIG9yIHNtYWxsIHZhbHVlcy4gSW4gdGhpcyBgc2xlZXBgIGRhdGFzZXQsIHRoZSBkaWZmZXJlbmNlcyBtaWdodCBub3QgYmUgcGVyZmVjdGx5IG5vcm1hbCwgZ2l2aW5nIHRoZSBXaWxjb3hvbiB0ZXN0IGFuIGFkdmFudGFnZSBpbiBkZXRlY3RpbmcgYSByZWFsIGVmZmVjdC4KCiMjIyBUZXN0IDIxIFBhaXJ3aXNlIFBhaXJlZCB0LXRlc3QgZm9yIHRoZSBEaWZmZXJlbmNlIGluIFNhbXBsZSBNZWFucwoKUXVlc3Rpb24gdG8gdGhlIHRlc3QgYWRkcmVzc2VzOgoKKipJcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBtZWFuIG9mIHR3byBzYW1wbGVzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gemVybywgd2hlbiB0ZXN0ZWQgYWNyb3NzIG11bHRpcGxlIHBhaXJzPyoqCgpUbyB1c2UgdGhpcyB0ZXN0OgoKLSAgIG11bHRpcGxlIHNhbXBsZXMKCi0gICBtYXRjaGVkIHBhaXJzIGV4cGVyaW1lbnRhbCBkZXNpZ24KCi0gICBzdWJqZWN0cyBhcmUgYXNzdW1lZCB0byBiZSBub3JtYWxseSBkaXN0cmlidXRlZAoKV2Ugd2lsbCB1c2UgdGhlIGJ1aWx0LWluIGRhdGFzZXQgYGlyaXNgIHRvIGV4YW1pbmUgdGhlIGRpZmZlcmVuY2UgaW4gdGhlIGxlbmd0aCBvZiBzZXBhbC4gVGhlIGBpcmlzYCBkYXRhc2V0IGNvbnRhaW5zIG1lYXN1cmVtZW50cyBmb3IgNTAgZmxvd2VycyBmcm9tIDMgZGlmZmVyZW50IHNwZWNpZXMuIExldCdzIHByZXRlbmQgZm9yIHRoaXMgZXhlcmNpc2UgdGhhdCB0aGVzZSBhcmVuJ3QgdGhyZWUgc2VwYXJhdGUgc3BlY2llcywgYnV0IGFyZSBpbnN0ZWFkIG1lYXN1cmVtZW50cyBvZiB0aGUgKipzYW1lIDUwIGZsb3dlcnMqKiBhdCB0aHJlZSBkaWZmZXJlbnQgcG9pbnRzIGluIHRpbWUgKFRpbWUgMSwgVGltZSAyLCBUaW1lIDMpLiBUaGlzIGxldHMgdXMgcHJhY3RpY2UgYSBwYWlyZWQgYW5hbHlzaXMuCgpgYGB7ciB0ZXN0IDIxLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwYWlyd2lzZS50LnRlc3QoaXJpcyRTZXBhbC5MZW5ndGgsIGlyaXMkU3BlY2llcywgcGFpcmVkID0gVFJVRSwgcC5hZGp1c3QubWV0aG9kID0gImhvbG0iKQpgYGAKCkFjY29yZGluZyB0byB0aGUgcmVzdWx0LCB3ZSBjYW4gZmluZCB0aGF0IHRoZSBwLXZhbHVlcyBhY3Jvc3MgYWxsIHBhaXJzIGFyZSBzbWFsbGVyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlIDAuMDUuIFRoZXJlZm9yZSwgd2UgY2FuIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlcmUgaXMgbm8gc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBpbiB0aGUgbGVuZ3RoIG9mIHNlcGFsIGJldHdlZW4gYW55IG9mIHRoZSB0aHJlZSB0aW1lIHBvaW50cy4KCiMjIyBUZXN0IDIyIFBhaXJ3aXNlIFdpbGNveCBUZXN0IGZvciB0aGUgRGlmZmVyZW5jZSBpbiBTYW1wbGUgTWVhbnMKClF1ZXN0aW9uIHRvIHRoZSB0ZXN0IGFkZHJlc3NlczoKCioqSXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbWVhbiBvZiB0d28gc2FtcGxlcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIHplcm8sIHdoZW4gdGVzdGVkIGFjcm9zcyBtdWx0aXBsZSBwYWlycz8qKgoKVG8gdXNlIHRoaXMgdGVzdDoKCi0gICBzYW1lIHdpdGggY29uZGl0aW9ucyBpbiB0ZXN0IDIxCgotICAgY2FuIG5vdCBhc3N1bWUgdG8gYmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQKCldlIGtlZXAgb3VyIGFzc3VtcHRpb24gdGhhdCB3ZSBzZXQgaW4gdGVzdCAyMS4KCmBgYHtyIHRlc3QgMjIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnBhaXJ3aXNlLndpbGNveC50ZXN0KGlyaXMkU2VwYWwuTGVuZ3RoLCBpcmlzJFNwZWNpZXMsIHBhaXJlZCA9IFRSVUUsIHAuYWRqdXN0Lm1ldGhvZCA9ICJob2xtIikKYGBgCgpBY2NvcmRpbmcgdG8gdGhpcyByZXN1bHQsIHdlIGNhbiBnZXQgdGhlIHNhbWUgY29uY2x1c2lvbiBiYXNlZCBvbiB0aGUgcC12YWx1ZS4KCiMjIyBUZXN0IDIzIFR3by1zYW1wbGUgRGVwZW5kZW50IFNpZ24gUmFuayBUZXN0IGZvciBEaWZmZXJlbmNlIGluIE1lZGlhbnMKClF1ZXN0aW9uIHRvIHRoZSB0ZXN0IGFkZHJlc3NlczoKCioqSXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbWVkaWFuIG9mIHR3byByZWxhdGVkIHNhbXBsZXMgc2lnbmlmaWNhbnRseSBmcm9tIHplcm8/KioKClRvIHVzZSB0aGlzIHRlc3Q6CgotICAgZWFjaCBzdWJqZWN0IGlzIG1lYXN1cmVkIHR3aWNlLCBiZWZvcmUgYW5kIGFmdGVyCgotICAgYSBtYXRjaGVkIHBhaXJzIGV4cGVyaW1lbnRhbCBkZXNpZ24KCi0gICBjb250aW51b3VzIGRpc3RyaWJ1dGlvbgoKV2Ugd2lsbCB1c2UgdGhlIGBzbGVlcGAgZGF0YXNldC4gV2Ugd2lsbCBhbHNvIG5lZWQgdGhlIGZ1bmN0aW9uIGBTSUdOLnRlc3QoKWAgZnJvbSBgQlNEQWAgcGFja2FnZS4KCmBgYHtyIHRlc3QgMjMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmRydWcxX3NsZWVwIDwtIHNsZWVwJGV4dHJhW3NsZWVwJGdyb3VwID09IDFdCmRydWcyX3NsZWVwIDwtIHNsZWVwJGV4dHJhW3NsZWVwJGdyb3VwID09IDJdCgpTSUdOLnRlc3QoZHJ1ZzFfc2xlZXAsIGRydWcyX3NsZWVwKQpgYGAKCkFjY29yZGluZyB0byB0aGUgcmVzdWx0LCB3ZSBjYW4gZmluZCB0aGUgcC12YWx1ZSBpcyBzbWFsbGVyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlLiBUaGVyZWZvcmUsIHdlIGNhbiByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4KCiMjIyBUZXN0IDI0IFdpbGNveG9uIFJhbmsgU3VtIFRlc3QgZm9yIHRoZSBEaWZmZXJlbmNlIGluIE1lZGlhbnMKClF1ZXN0aW9uIHRvIHRoZSB0ZXN0IGFkZHJlc3NlczoKCioqSXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbWVkaWFuIG9mIHR3byBzYW1wbGVzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gemVybz8qKgoKVG8gdXNlIHRoaXMgdGVzdDoKCi0gICBEYXRhIGFyZSBub3QgYXNzdW1lZCB0byBiZSBub3JtYWxseSBkaXN0cmlidXRlZAoKLSAgIFR3byBpbmRlcGVuZGVudCBncm91cHMKCi0gICB3b3JrcyB3aXRoIHJhbmsgb2YgdGhlIGRhdGEKCldlIHdpbGwgdXNlIHRoZSBgY2hpY2t3dHNgIG9uZSBsYXN0IHRpbWUgdG8gY29tcGFyZSBpdCB3aXRoIHRoZSB0LXRlc3RzLgoKYGBge3IgdGVzdCAyNCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZmVlZHNfdG9fY29tcGFyZSA8LSBjaGlja3d0cyAlPiUgCiAgZmlsdGVyKGZlZWQgJWluJSBjKCJjYXNlaW4iLCAic295YmVhbiIpKQoKd2lsY294LnRlc3Qod2VpZ2h0IH4gZmVlZCwgZGF0YSA9IGZlZWRzX3RvX2NvbXBhcmUpCmBgYAoKQWNjb3JkaW5nIHRvIHRoZSByZXN1bHQsIHdlIGNhbiBmaW5kIHRoYXQgdGhlIHAtdmFsdWUgaXMgc21hbGxlciB0aGFuIHRoZSBjcml0aWNhbCB2YWx1ZS4gVGhlcmVmb3JlLCB3ZSBjYW4gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMuCgojIyBUZXN0IDI1LTMxIEEgRGVlcCBEaXZlIGludG8gUmFuZG9tbmVzcwoKIyMjIFRlc3QgMjUgV2FsZC1Xb2xmb3dpdHogUnVucyBUZXN0IGZvciBEaWNob3RvbW91cyBEYXRhCgpUaGlzIHRlc3QgaXMgdXNlZCB0byBjaGVjayBmb3IgcmFuZG9tbmVzcyBpbiBhIHNlcXVlbmNlIG9mICoqYmluYXJ5IGV2ZW50cyoqLiBCaW5hcnkgZGF0YSBtZWFucyB0aGF0IGRhdGEgd2l0aCBvbmx5IHR3byBjYXRlZ29yaWVzLCBsaWtlIFllcy9Obywgb3IgMC8xLgoKVGhpcyB0ZXN0IGRldGVjdHMgdGhlICoqcnVucyoqIGluIGEgc2VxdWVuY2Ugb2YgZGF0YS4gQSAqKnJ1bioqIG1lYW5zIHRoZSB1bmludGVycnVwdGVkIHNlcXVlbmNlIG9mIHRoZSBzYW1lIGV2ZW50LiBGb3IgZXhhbXBsZSwgaW4gdGhlIHNlcXVlbmNlIGAxLCAxLCAxLCAwLCAwLCAxLCAwLCAwLCAwYCwgdGhlcmUgYXJlIDQgcnVucyAoYDExMWAsIGAwMGAsIGAxYCwgYDAwMGApLiBJZiB0aGVyZSBhcmUgdG9vIGZldyBvciB0b28gbWFueSBydW5zLCBpdCBzdWdnZXN0cyB0aGUgc2VxdWVuY2UgaXNuJ3QgcmFuZG9tLgoKV2Ugd2lsbCB1c2UgdGhlIGBydW5zLnRlc3QoKWAgZnJvbSBgdHNlcmllc2AgcGFja2FnZS4KCmBgYHtyIFRlc3QgMjUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmlmICghcmVxdWlyZSgidHNlcmllcyIpKSB7CiAgaW5zdGFsbC5wYWNrYWdlcygidHNlcmllcyIpCiAgbGlicmFyeSh0c2VyaWVzKQp9CgpiaW5hcnlfc2VxdWVuY2UgPC0gZmFjdG9yKGMoMSwxLDAsMCwxLDAsMSwxLDEsMCwwLDApKQoKcnVucy50ZXN0KGJpbmFyeV9zZXF1ZW5jZSkKYGBgCgpBY2NvcmRpbmcgdG8gdGhpcyByZXN1bHQsIHdlIGNhbiBmaW5kIHRoYXQgdGhlIHAtdmFsdWUgaXMgbGFyZ2VyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlIDAuMDUuIFRoZXJlZm9yZSwgd2UgY2FuIG5vdCByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IG91ciBiaW5hcnkgc2VxdWVuY2UgaXMgcmFuZG9tLgoKIyMjIFRlc3QgMjYgV2FsZC1Xb2xmb3dpdHogUnVucyBUZXN0IGZvciBDb250aW51b3VzIERhdGEKClRoaXMgdGVzdCBleHRlbmRzIHRoZSB0ZXN0IDI1IGludG8gY29udGludW91cyBkYXRhLiBRdWVzdGlvbiB0byB0aGlzIHRlc3QgYWRkcmVzc2VzOgoKKipJcyB0aGUgc2VxdWVuY2Ugb2Ygb2JzZXJ2YXRpb25zIGluIGEgc2FtcGxlIHJhZG9tbHkgZGlzdHJpYnV0ZWQ/KioKCkl0IHdvcmtzIGZvciBjb250aW51b3VzIGRhdGEuCgpXZSB3aWxsIHVzZSB0aGUgYHJ1bnMudGVzdCgpYCBmcm9tIHRoZSBgbGF3c3RhdGAgcGFja2FnZSBmb3IgdGhpcy4KCmBgYHtyIHRlc3QgMjYsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmlmICghcmVxdWlyZSgibGF3c3RhdCIpKSB7CiAgaW5zdGFsbC5wYWNrYWdlcygibGF3c3RhdCIpCiAgbGlicmFyeShsYXdzdGF0KQp9Cgpjb250aW51b3VzX3NlcXVlbmNlIDwtIGMoMS44LCAyLjMsIDEuNSwgMi45LCAxLjEsIDMuNSwgMC45KQoKcnVucy50ZXN0KGNvbnRpbnVvdXNfc2VxdWVuY2UpCmBgYAoKQWNjb3JkaW5nIHRvIHRoaXMgcmVzdWx0LCB3ZSBjYW4gZmluZCB0aGF0IHRoZSBwLXZhbHVlIGlzIHNtYWxsZXIgdGhhbiBjcml0aWNhbCB2YWx1ZSAwLjA1LiBUaGVyZWZvcmUsIHdlIGNhbiByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IG91ciBjb250aW51b3VzIHNlcXVlbmNlIGlzIHJhbmRvbS4KCiMjIyBUZXN0IDI3IEJhcnRlbHMgVGVzdCBvZiBSYW5kb21uZXNzIGluIGEgU2FtcGxlCgpRdWVzdGlvbiB0byB0aGUgdGVzdCBhZGRyZXNzZXM6CgoqKklzIHRoZSBzZXF1ZW5jZSBvZiBvYnNlcnZhdGlvbnMgaW4gYSBzYW1wbGUgcmFuZG9tbHkgZGlzdHJpYnV0ZWQ/KioKCkJhcnRlbHMgdGVzdCBpcyBhIHBvd2VyZnVsIGFsdGVyYW50aXZlIHRvIHRoZSBXYWxkLVdvbGZvd2l0eiBydW5zIHRlc3QgZm9yIGNvbnRpbnVvdXMgZGF0YS4gSXQncyBiYXNlZCBvbiB0aGUgcmFua3Mgb2YgZGF0YSByYXRoZXIgdGhhbiBqdXN0IHRoZWlyIHBvc2l0aW9uIHJlbGF0aXZlIHRvIHRoZSBtZWRpYW4uCgpUaGUgZnVuY3Rpb24gaXMgYGJhcnRlbHMudGVzdCgpYCBmcm9tIHRoZSBzYW1lIGBsYXdzdGF0YCBwYWNrYWdlLiBXZSB3aWxsIHVzZSB0aGUgc2FtZSBjb250aW51b3VzIGluIHRoZSB0ZXN0IDI2IGluIHRoaXMgdGVzdC4KCmBgYHtyIHRlc3QgMjcsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmJhcnRlbHMudGVzdChjb250aW51b3VzX3NlcXVlbmNlKQpgYGAKCkFjY29yZGluZyB0byB0aGUgcmVzdWx0LCB3ZSBjYW4gZmluZCB0aGF0IHAtdmFsdWUgaXMgbGFyZ2VyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlIDAuMDUuIFRoZXJlZm9yZSwgd2UgY2FuIG5vdCByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IG91ciBjb250aW51b3VzIHNlcXVlbmNlIGlzIHJhbmRvbS4KClRoZSBXYWxkLVdvbGZvd2l0eiB0ZXN0IGdhdmUgYSBwLXZhbHVlIG9mIDAuMDA2IChzaWduaWZpY2FudCksIHdoaWxlIHRoZSBCYXJ0ZWxzIHRlc3QgZ2F2ZSAwLjA5OCAobm90IHNpZ25pZmljYW50KS4gV2hpbGUgdGhlIEJhcmxldHMgdGVzdCBpcyBvZnRlbiBtb3JlIHBvd2VyZnVsLCBpdCdzIG5vdCBhIHVuaXZlcnNhbCBydWxlLiBEaWZmZXJlbnQgdGVzdHMgYXJlIHNlbnNpdGl2ZSB0byBkaWZmZXJlbnQga2luZHMgb2Ygbm9uLXJhbmRvbSBwYXR0ZXJucy4gSW4gb3VyIGV4YW1wbGUsIHRoZSB2ZXJ5IHNob3J0IHNlcXVlbmNlLCB0aGV5IHdheSB0aGUgdHdvIHRlc3RzIGNhbGN1bGF0ZSB0aGVpciBzdGF0aXN0aWNzIGxlZCB0aGVtIHRvIGRpZmZlcmVudCBjb25jbHVzaW9ucy4KCiMjIyBUZXN0IDI4ICYgMjkgTGp1bmctQm94IGFuZCBCb3gtUGllcmNlIFRlc3RzCgpCb3RoIHRoZSAqKkxqdW5nLUJveCoqIGFuZCAqKkJveC1QaWVyY2UqKiB0ZXN0cyBjaGVjayBmb3IgKiphdXRvY29ycmVsYXRpb24qKiBpbiBhIHRpbWUgc2VyaWVzLgoKUXVlc3Rpb24gdG8gdGhlc2UgdGVzdHMgYWRkcmVzczoKCioqSXMgdGhlIHNlcXVlbmNlIG9mIG9ic2VydmF0aW9ucyBpbiBhIHNhbXBsZSByYW5kb21seSBkaXN0cmlidXRlZD8qKgoKVGhlc2UgdGVzdHMgY2hlY2sgaWYgdGhlIGF1dG9jb3JyZWxhdGlvbnMgYmV0d2VlbiB0aGUgc2VyaWVzIGFuZCBpdHMgcGFzdCB2YWx1ZXMgYXJlIGFsbCB6ZXJvLiBUaGUgKipManVuZy1Cb3gqKiB0ZXN0IGlzIGEgcmVmaW5lbWVudCBvZiB0aGUgKipCb3gtUGllcmNlKiogdGVzdCBhbmQgaXMgZ2VuZXJhbGx5IHByZWZlcnJlZCBmb3Igc21hbGwgc2FtcGxlIHNpemVzLgoKV2Ugd2lsbCB1c2UgdGhlIGJ1aWx0LWluIGBOaWxlYCBkYXRhc2V0IGNvbnRhaW5zIG1lYXN1cmVtZW50cyBvZiB0aGUgZmxvdyBvZiB0aGUgcml2ZXIgTmlsZSBmcm9tIDE4NzEtMTk3MC4KCmBgYHtyIHRlc3QgMjggMjkgZGF0YSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGxvdChOaWxlKQpgYGAKCmBgYHtyIHRlc3QgMjggMjksIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CkJveC50ZXN0KE5pbGUsIGxhZyA9IDEwLCB0eXBlID0gIkxqdW5nLUJveCIpCkJveC50ZXN0KE5pbGUsIGxhZyA9MTAsIHR5cGUgPSAiQm94LVBpZXJjZSIpCmBgYAoKQWNjb3JkaW5nIHRvIHRoZXNlIHJlc3VsdHMsIHdlIGNhbiBmaW5kIHRoYXQgdGhlIHAtdmFsdWVzIGFyZSBib3RoIHNtYWxsZXIgdGhhbiB0aGUgY3JpdGljYWwgdmFsdWUgMC4wNS4gVGhlcmVmb3JlLCB3ZSBjYW4gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCB0aGUgbWVhc3VyZW1lbnRzIG9mIHRoZSByaXZlciBOaWxlIGlzIHJhbmRvbS4KCiMjIyBUZXN0IDMwIEJEUyB0ZXN0CgpRdWVzdGlvbiB0byB0aGUgdGVzdCBhZGRyZXNzZXM6CgoqKklzIGEgdGltZSBzZXJpZXMgaW5kZXBlbmRlbnQgYW5kIGlkZW50aWNhbGx5IGRpc3RyaWJ1dGVkPyoqCgpUbyB1c2UgdGhpcyB0ZXN0OgoKLSAgIGRldGVjdCBjb21wbGV4IGFuZCBub24tbGluZWFyIHBhdHRlcm5zCgotICAgc2luZ2xlIHRpbWUgc2VyaWVzCgpXZSB3aWxsIGNvbnRpbnVlIHRvIHVzZSB0aGUgYE5pbGVgIGRhdGFzZXQgYW5kIGNoZWNrIGlmIHRoZXJlIGlzIGFueSBub24tcmFuZG9tIG9yIG5vbi1saW5lYXIgcGF0dGVybnMuCgpgYGB7ciB0ZXN0IDMwLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpiZHMudGVzdChOaWxlKQpgYGAKCkFjY29yZGluZyB0byB0aGUgcmVzdWx0LCB3ZSBjYW4gZmluZCB0aGF0IGFsbCBwLXZhbHVlcyBhcmUgc21hbGxlciB0aGFuIHRoZSBjcml0aWNhbCB2YWx1ZSAwLjA1LiBUaGVyZWZvcmUsIHdlIGNhbiByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZSBOaWxlIGRhdGFzZXQgaXMgaW5kZXBlbmRlbnQgYW5kIGlkZW50aWNhbGx5IGRpc3RyaWJ1dGVkLiBJdCBzdWdnZXN0cyB0aGUgcGF0dGVybnMgaW4gdGhlIE5pbGUgZGF0YXNldCBhcmUgbW9yZSBjb21wbGV4IGFuZCBtYXliZSBub24tbGluZWFyLgoKIyMjIFRlc3QgMzEgV2FsZC1Xb2xmb3dpdHogVHdvLVNhbXBsZSBSdW4gdGVzdAoKUXVlc3Rpb24gdG8gdGhlIHRlc3QgYWRkcmVzc2VzOgoKKipEbyB0d28gaW5kZXBlbmRlbnQgc2FtcGxlcyBjb21lIGZyb20gcG9wdWxhdGlvbnMgaGF2aW5nIHRoZSBzYW1lIGRpc3RyaWJ1dGlvbj8qKgoKVG8gdXNlIHRoaXMgdGVzdDoKCi0gICBjb21iaW5pbmcgdHdvIHNhbXBsZXMgdG9nZXRoZXIKCi0gICByYW5raW5nIHdpdGggdGhlIHJ1biB0ZXN0CgpXZSB3aWxsIHVzZSB0aGUgTmlsZSBkYXRhc2V0IHRvIHNlZSB3aGV0aGVyIHRoZSBmaXJzdCA1MCB5ZWFycyBhcmUgZGlmZmVyZW50IGZyb20gdGhlIGxhc3QgNTAgeWVhcnMuCgpgYGB7ciB0ZXN0IDMxIGRhdGEsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cm5pbGVfZmlyc3RfNTAgPC0gTmlsZVsxOjUwXQpuaWxlX2xhc3RfNTAgPC0gTmlsZVs1MToxMDBdCnBsb3QobmlsZV9maXJzdF81MCkKcGxvdChuaWxlX2xhc3RfNTApCmBgYAoKYGBge3IgdGVzdCAzMSAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmNvbWJpbmVkX25pbGUgPC0gYyhuaWxlX2ZpcnN0XzUwLG5pbGVfbGFzdF81MCkKZ3JvdXBfbGFiZWxzIDwtIGZhY3RvcihjKHJlcCgiZmlyc3QiLCA1MCksIHJlcCgibGFzdCIsIDUwKSkpCgpzb3J0ZWRfZ3JvdXBzIDwtIGdyb3VwX2xhYmVsc1tvcmRlcihjb21iaW5lZF9uaWxlKV0KdHNlcmllczo6cnVucy50ZXN0KHNvcnRlZF9ncm91cHMpCmBgYAoKQWNjb3JkaW5nIHRvIHRoZSByZXN1bHQsIHdlIGNhbiBmaW5kIHRoYXQgdGhlIHAtdmFsdWUgaXMgc21hbGxlciB0aGFuIHRoZSBjcml0aWNhbCB2YWx1ZSAwLjA1LiBUaGVyZWZvcmUsIHdlIGNhbiByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZXJlIGlzIG5vIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgZmlyc3QgNTAgeWVhcnMgYW5kIGxhc3QgNTAgeWVhcnMuIFRoZSB0ZXN0IHN1Z2dlc3RzIHRoYXQgdGhlIHR3byBzYW1wbGVzIGFyZSBub3QgcmFuZG9tbHkgbWl4ZWQsIHdoaWNoIG1lYW5zIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIE5pbGUncyBmbG93IGluIHRoZSBmaXJzdCA1MCB5ZWFycyBpcyBsaWtlbHkgZGlmZmVyZW50IGZyb20gaXRzIGRpc3RyaWJ1dGlvbiBpbiB0aGUgbGFzdCA1MCB5ZWFycy4KCiMjIFZhcmlhbmNlcyBhbmQgRGlzcGVyc2lvbgoKIyMjIFRlc3QgMzIgTW9vZCdzIFRlc3QKClF1ZXN0aW9uIHRvIHRoZSB0ZXN0IGFkZHJlc3NlczoKCioqRG8gdHdvIGluZGVwZW5kZW50IHNhbXBsZXMgY29tZSBmcm9tIHRoZSBzYW1lIGRpc3RyaWJ1dGlvbj8qKgoKVG8gdXNlIHRoaXMgdGVzdDoKCi0gICB0d28gc2FtcGxlcyBhcmUgYXNzdW1lZCB0byBoYXZlIHNhbWUgbWVkaWFucyBhbmQgc2hhcGUKCldlIHdpbGwgY29tcGFyZSB0aGUgc3ByZWFkIG9mIHdlaWdodHMgZm9yIGNoaWNrcyBmZWQgKioiY2FzZWluIioqIHZlcnN1cyB0aG9zZSBmZWQgKioic3VuZmxvd2VyIioqLiBWaXN1YWxseSwgdGhlaXIgYXZlcmFnZSB3ZWlnaHRzIGxvb2sgc2ltaWxhciwgYnV0IGlzIHRoZSBjb25zaXN0ZW5jeSBvZiB0aGUgd2VpZ2h0IGdhaW4gdGhlIHNhbWU/Cgp3ZSBjYW4gdXNlIHRoZSBgbW9vZC50ZXN0KClgIGZ1bmN0aW9uLgoKYGBge3IgdGVzdCAzMiBkYXRhIHByZXBhcmF0aW9uLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpjYXNlaW5fdl9zdW5mbG93ZXIgPC0gY2hpY2t3dHMgJT4lCiAgZmlsdGVyKGZlZWQgJWluJSBjKCJjYXNlaW4iLCAic3VuZmxvd2VyIikpCgpnZ3Bsb3QoY2FzZWluX3Zfc3VuZmxvd2VyLCBhZXMoeCA9IGZlZWQsIHkgPSB3ZWlnaHQsIGZpbGwgPSBmZWVkKSkgKwogIGdlb21fYm94cGxvdCgpICsKICBsYWJzKHRpdGxlID0gIkNvbXBhcmlzb24gb2YgQ2hpY2sgV2VpZ2h0cyBieSBGZWVkIFR5cGUiLAogICAgICAgeCA9ICJGZWVkIFR5cGUiLAogICAgICAgeSA9ICJXZWlnaHQgKGdyYW1zKSIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgpgYGB7ciB0ZXN0IDMyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQptb29kLnRlc3Qod2VpZ2h0IH4gZmVlZCwgZGF0YSA9IGNhc2Vpbl92X3N1bmZsb3dlcikKYGBgCgpBY2NvcmRpbmcgdG8gdGhlIHJlc3VsdCwgd2UgY2FuIGZpbmQgdGhhdCB0aGUgcC12YWx1ZSBpcyBsYXJnZXIgdGhhbiB0aGUgY3JpdGljYWwgdmFsdWUgMC4wNS4gVGhlcmVmb3JlLCB3ZSBjYW4gbm90IHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlc2UgdHdvIGluZGVwZW5kZW50IHNhbXBsZXMgY29tZSBmcm9tIHRoZSBzYW1lIGRpc3RyaWJ1dGlvbi4KCiMjIyBUZXN0IDMzIEYtdGVzdCBvZiBFcXVhbGl0eSBvZiBWYXJpYW5jZXMKClF1ZXN0aW9uIHRvIHRoZSB0ZXN0IGFkZHJlc3NlczoKCioqQXJlIHRoZSB2YXJpYW5jZXMgb2YgdHdvIHNhbXBsZXMgZXF1YWw/KioKClRvIHVzZSB0aGlzIHRlc3Q6CgotICAgaGlnaGx5IHNlbnNpdGl2ZSB0byB0aGUgZGF0YSBiZWluZyBub3JtYWxseSBkaXN0cmlidXRlZAoKLSAgIHBhcmFtZXRyaWMgdGVzdCwgdmVyeSBwb3dlcmZ1bAoKV2Ugd2lsbCB1c2UgdGhlIEYtdGVzdCBvbiB0aGUgc2FtZSB0d28gZ3JvdXBzOiAiY2FzZWluIiB2cy4gInN1bmZsb3dlciIuIFRoaXMgd2lsbCBsZXQgdXMgY29tcGFyZSB0aGUgcmVzdWx0IGZyb20gYSBwYXJhbWV0cmljIHRlc3QgKEYtdGVzdCkgdG8gdGhlIG5vbnBhcmFtZXRyaWMgb25lIChNb29kJ3MgdGVzdCkuIFRoZSBmdW5jdGlvbiBmb3IgRi10ZXN0IGlzIGB2YXIudGVzdCgpYC4KCmBgYHtyIHRlc3QgMzMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmNhc2Vpbl92X3N1bmZsb3dlciA8LSBjaGlja3d0cyAlPiUgCiAgZmlsdGVyKGZlZWQgJWluJSBjKCJjYXNlaW4iLCAic3VuZmxvd2VyIikpCgp2YXIudGVzdCh3ZWlnaHQgfiBmZWVkLCBkYXRhID0gY2FzZWluX3Zfc3VuZmxvd2VyKQpgYGAKCkFjY29yZGluZyB0byB0aGUgcmVzdWx0LCB3ZSBjYW4gZmluZCB0aGF0IHRoZSBwLXZhbHVlIGlzIGxhcmdlciB0aGFuIHRoZSBjcml0aWNhbCB2YWx1ZS4gVGhlcmVmb3JlLCB3ZSBjYW4gbm90IHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlIHZhcmlhbmNlcyBvZiBjYXNlaW4gZ3JvdXAgYW5kIHN1bmZsb3dlciBncm91cCBhcmUgZXF1YWwuCgojIyMgVGVzdCAzNCBQaXRtYW4tTW9yZ2FuIFRlc3QKClF1ZXN0aW9uIHRvIHRoZSB0ZXN0IGFkZHJlc3NlczoKCioqQXJlIHRoZSB2YXJpYW5jZXMgb2YgdHdvIGNvcnJlbGF0ZWQgc2FtcGxlIGVxdWFsPyoqCgpUbyB1c2UgdGhpcyB0ZXN0OgoKLSAgIHBhaXJlZCBkYXRhCgotICAgdGVzdGluZyB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiBzdW0gYW5kIHZhcmlhbmNlcwoKLSAgIGhpZ2hseSBzZW5zaXRpdmUgdG8gdGhlIGRhdGEgYmVpbmcgbm9ybWFsbHkgZGlzdHJpYnV0ZWQKCldlIHdpbGwgdXNlIGBzbGVlcGAgZGF0YXNldCBhZ2FpbiwgYXMgaXQgY29udGFpbnMgcGFpcmVkIGRhdGEgKGVhY2ggb2YgdGhlIDEwIHN1YmplY3RzIHdhcyB0ZXN0ZWQgb24gdHdvIGRpZmZlcmVudCBkcnVncykuIFdlIGNhbiB0ZXN0IGlmIHRoZSB2YXJpYW5jZSBpbiAiZXh0cmEgc2xlZXAiIHdhcyBkaWZmZXJlbnQgZm9yIERydWcgMSBjb21wYXJlZCB0byBEcnVnIDIuCgpUaGUgZnVuY3Rpb24gZm9yIHRoaXMgaXMgYHBpdG1hbi5tb3JnYW4udGVzdC5kZWZhdWx0KClgIGZyb20gdGhlIGBQYWlyZWREYXRhYCBwYWNrYWdlLgoKYGBge3IgdGVzdCAzNCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KaWYgKCFyZXF1aXJlKCJQYWlyZWREYXRhIikpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJQYWlyZWREYXRhIikKICBsaWJyYXJ5KFBhaXJlZERhdGEpCn0KcGl0bWFuLm1vcmdhbi50ZXN0LmRlZmF1bHQoZHJ1ZzFfc2xlZXAsIGRydWcyX3NsZWVwKQpgYGAKCkFjY29yZGluZyB0byB0aGUgcmVzdWx0LCB3ZSBjYW4gZmluZCB0aGF0IHRoZSBwLXZhbHVlIGlzIGxhcmdlciB0aGFuIHRoZSBjcml0aWNhbCB2YWx1ZSAwLjA1LiBUaGVyZWZvcmUsIHdlIGNhbiBub3QgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCB0aGUgdmFyaWFuY2VzIGZyb20gZHJ1ZyAxIGFuZCBkcnVnIDIgYXJlIGVxdWFsLgoKIyMgVGVzdCAzNS00MCBUaGUgSG9tb2dlbmVpdHkgb2YgVmFyaWFuY2UgRmFtaWx5CgpBbGwgdGhlc2Ugc2VyaWVzIG9mIHRlc3RzIGFpbSB0byBhbnN3ZXIgdGhlIHNhbWUgcXVlc3Rpb246CgoqKkRvIG11bHRpcGxlIGluZGVwZW5kZW50IHNhbXBsZXMgY29tZSBmcm9tIHBvcHVsYXRpb25zIHdpdGggZXF1YWwgdmFyaWFuY2VzPyoqCgojIyMgVGVzdCAzNSBBbnNhcmktQnJhZGxleSBUZXN0CgpUbyB1c2UgdGhpcyB0ZXN0OgoKLSAgIGRhdGEgYXJlIGFzc3VtZWQgdG8gYmUgY29udGludW91cwoKLSAgIGRhdGEgYXJlIG1lYXN1cmVkIGF0IG9yZGluYXJ5IHNjYWxlCgpXZSB3aWxsIHVzZSB0aGUgZnVsbCBgY2hpY2t3dHNgIGRhdGFzZXQsIHdoaWNoIGhhcyBzaXggZmVlZCBncm91cHMsIHRvIHRlc3QgaWYgdGhlIHZhcmlhbmNlIGluIHdlaWdodCBpcyB0aGUgc2FtZSBhY3Jvc3MgKiphbGwqKiBvZiB0aGVtLiBXZSdsbCBzdGFydCB3aXRoIHRoZSAqKkFuc2FyaS1CcmFkbGV5IFRlc3QqKi4KCmBgYHtyIHRlc3QgMzV9CmNhc2Vpbl92X3N1bmZsb3dlciA8LSBjaGlja3d0cyAlPiUKICBmaWx0ZXIoZmVlZCAlaW4lIGMoImNhc2VpbiIsICJzdW5mbG93ZXIiKSkKCmFuc2FyaS50ZXN0KHdlaWdodCB+IGZlZWQsIGRhdGEgPSBjYXNlaW5fdl9zdW5mbG93ZXIpCmBgYAoKQWNjb3JkaW5nIHRvIHRoZSByZXN1bHQsIHdlIGNhbiBmaW5kIHRoYXQgcC12YWx1ZSBpcyBsYXJnZXIgdGhhbiB0aGUgY3JpdGljYWwgdmFsdWUgMC4wNS4gVGhlcmVmb3JlLCB3ZSBjYW4gbm90IHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlc2UgdHdvIHNhbXBsZXMgaGF2ZSB0aGUgc2FtZSB2YXJpYW5jZXMuCgojIyMgVGVzdCAzNiBCYXJ0bGV0dCBUZXN0CgpUbyB1c2UgdGhpcyB0ZXN0OgoKLSAgIHNlbnNpdGl2ZSB0byBkYXRhIGJlaW5nIG5vcm1hbCBkaXN0cmlidXRpb24KCldlIHdpbGwgdXNlIGBjaGlja3d0c2AgZGF0YXNldCB0byBjb21wYXJlIHZhcmlhbmNlcyBmcm9tIGFsbCBmZWVkcy4KCmBgYHtyIHRlc3QgMzYsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmJhcnRsZXR0LnRlc3Qod2VpZ2h0IH4gZmVlZCwgZGF0YSA9IGNoaWNrd3RzKQpgYGAKCkFjY29yZGluZyB0byB0aGUgcmVzdWx0cywgd2UgY2FuIGZpbmQgdGhhdCB0aGUgcC12YWx1ZSBpcyBsYXJnZXIgdGhhbiB0aGUgY3JpdGljYWwgdmFsdWUuIFRoZXJlZm9yZSwgd2UgY2FuIG5vdCByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHZhcmlhbmNlcyBmcm9tIGFsbCBmZWVkIGFyZSB0aGUgc2FtZS4KCiMjIyBUZXN0IDM3IEZsaWduZXItS2lsbGVlbiBUZXN0CgotICAgbm9ucGFyYW1ldHJpYyB0ZXN0CgotICAgbW9yZSByb2J1c3QKCi0gICBkYXRhIGNhbiBiZSBhc3N1bWVkIG5vdCB0byBiZSBub3JtYWxseSBkaXN0cmlidXRlZAoKV2Ugd2lsbCBjb21wYXJlIHRoZSByZXN1bHRzIGZyb20gRmxpZ25lci1LaWxlZW4gdGVzdCBhbmQgQmFydGxldHQgdGVzdCB0byBzZWUgYW55dGhpbmcgZGlmZmVyZW50LgoKYGBge3IgdGVzdCAzNywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZmxpZ25lci50ZXN0KHdlaWdodCB+IGZlZWQsIGRhdGEgPSBjaGlja3d0cykKYGBgCgpBY2NvcmRpbmcgdG8gdGhlIHJlc3VsdHMsIHdlIGdldCB0aGUgZXhhY3Qgc2FtZSBjb25jbHVzaW9uIHdpdGggQmFydGxldHQgdGVzdC4KCiMjIyBUZXN0IDM4IExldmVuZSdzIFRlc3Qgb2YgRXF1YWxpdHkgb2YgVmFyaWFuY2UKClRvIHVzZSB0aGlzIHRlc3Q6CgotICAgZGF0YSBhcmUgYXNzdW1lZCBub3QgdG8gYmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQKClRoZSBmdW5jdGlvbiBgbGV2ZW5lVGVzdCgpYCBpcyBpbiB0aGUgYGNhcmAgcGFja2FnZSwgd2hpY2ggd2UndmUgdXNlZCBiZWZvcmUuIExldCdzIHJ1biBpdCBvbiBvdXIgYGNoaWNrd3RzYCBkYXRhIHRvIHNlZSBpZiBvdXIgY29uY2x1c2lvbiBob2xkcyBhIHRoaXJkIHRpbWUuCgpgYGB7ciB0ZXN0IDM4LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQppZiAoIXJlcXVpcmUoImNhciIpKSB7CiAgaW5zdGFsbC5wYWNrYWdlcygiY2FyIikKICBsaWJyYXJ5KGNhcikKfQoKbGV2ZW5lVGVzdCh3ZWlnaHQgfiBmZWVkLCBkYXRhID0gY2hpY2t3dHMpCmBgYAoKQWNjb3JkaW5nIHRvIHRoZSByZXN1bHRzLCB3ZSBnZXQgdGhlIHNhbWUgcmVzdWx0IGFnYWluLgoKIyMjIFRlc3QgMzkgQ29jaHJhbidzIEMgVGVzdAoKUXVlc3Rpb24gdG8gdGhlIHRlc3QgYWRkcmVzc2VzOgoKKipJcyBzaW5nbGUgbGFyZ2VzdCB2YXJpYW5jZSBhbW9uZyBhIGdyb3VwIG9mIHNhbXBsZXMgYW4gb3V0bGllcj8qKgoKVG8gdXNlIHRoaXMgdGVzdDoKCi0gICBlcXVhbCBzYW1wbGUgc2l6ZSBhY3Jvc3MgYWxsIGdyb3VwcwoKLSAgIG1lYXN1cmUgdGhlIGxhcmdlc3QgdmFyaWFuY2VzIGFzIHRoZSBvdXRsaWVycwoKV2UnbGwgdXNlIHRoZSBgSW5zZWN0U3ByYXlzYCBkYXRhIGFuZCB0aGUgYGNvY2hyYW4udGVzdGAgZnVuY3Rpb24gZnJvbSB0aGUgYG91dGxpZXJzYCBwYWNrYWdlLgoKYGBge3IgdGVzdCAzOSBkYXRhIHByZXBhcmF0aW9uLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQppZiAoIXJlcXVpcmUoIm91dGxpZXJzIikpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJvdXRsaWVycyIpCiAgbGlicmFyeShvdXRsaWVycykKfQoKc3VtbWFyeShJbnNlY3RTcHJheXMpCmBgYAoKYGBge3IgdGVzdCAzOSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KY29jaHJhbi50ZXN0KGNvdW50IH4gc3ByYXksIGRhdGEgPSBJbnNlY3RTcHJheXMpCmBgYAoKQWNjb3JkaW5nIHRvIHRoZSByZXN1bHRzLCB3ZSBjYW4gZmluZCB0aGF0IHRoZSBwLXZhbHVlIGlzIHNtYWxsZXIgdGhhbiB0aGUgY3JpdGljYWwgdmFsdWUuIFRoZXJlZm9yZSwgd2UgY2FuIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlcmUgYXJlIG5vIHZhcmlhbmNlcyBhcyBvdXRsaWVycyBmcm9tIGFsbCBncm91cHMuIFRoZSB2YXJpYW5jZSBvZiAqKnNwcmF5IEYqKiBpcyBzaWduaWZpY2FudGx5IGxhcmdlciB0aGFuIHRoZSB2YXJpYW5jZXMgb2YgdGhlIG90aGVyIHNwcmF5cy4KCiMjIyBUZXN0IDQwIEJyb3duLUZvcnN5dGhlIFRlc3QKCi0gICB1c2UgbWVkaWFucyBmb3IgdGVzdAoKLSAgIG1vcmUgcm9idXN0IGFuZCBnZW5lcmFsLXB1cnBvc2UKCldlIHdpbGwgcnVuIHRoaXMgdGVzdCBvbiBgSW5zZWN0U3ByYXlzYCBkYXRhIHRvIHNlZSB3aGF0IGl0IHNheXMgYWJvdXQgdGhlIG92ZXJhbGwgZXF1YWxpdHkgb2YgdmFyaWFuY2VzLiBUaGUgZnVuY3Rpb24gaXMgYGxldmVuZS50ZXN0KClgIGZyb20gdGhlIGBsYXdzdGF0YCBwYWNrYWdlLCBhbmQgd2Ugc3BlY2lmeSBgbG9jYXRpb24gPSAibWVkaWFuImAgdG8gbWFrZSBpdCBhIEJyb3duLUZvcnN5dGhlIHRlc3QuCgpgYGB7ciB0ZXN0IDQwLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsZXZlbmUudGVzdChJbnNlY3RTcHJheXMkY291bnQsIEluc2VjdFNwcmF5cyRzcHJheSwgbG9jYXRpb24gPSAibWVkaWFuIikKYGBgCgpBY2NvcmRpbmcgdG8gdGhlIHJlc3VsdCwgd2UgY2FuIGZpbmQgdGhhdCB0aGUgcC12YWx1ZSBpcyBzbWFsbGVyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlLiBXZSBjYW4gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCB0aGUgdmFyaWFuY2VzIGFjcm9zcyBhbGwgZ3JvdXBzIGFyZSB0aGUgc2FtZS4KCiMjIyBUZXN0IDQxIE1hdWNobHkncyBTcGhlcmljaXR5IFRlc3QKClF1ZXN0aW9uIHRvIHRoZSB0ZXN0IGFkZHJlc3NlczoKCioqQXJlIHRoZSB2YXJpYW5jZXMgb2YgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gYWxsIHBvc3NpYmxlIHBhaXJzIG9mIGdyb3VwcyBpbiBhIHJlcGVhdGVkIG1lYXN1cmVzIGFuYWx5c2lzIG9mIHZhcmlhbmNlIGVxdWFsPyoqCgpUbyB1c2UgdGhpcyB0ZXN0OgoKLSAgIHZhcmlhbmNlcyBvZiB0aGUgZGlmZmVyZW5jZXMgb2YgY29tcGFyaXNvbiBncm91cHMgbmVlZCB0byBiZSBlcXVhbAoKLSAgIHJlcGVhdGVkIG1lYXN1cmVzIGZvciBBTk9WQSBhbmFseXNpcwoKV2Ugd2lsbCB1c2UgYENoaWNrV2VpZ2h0YCBhbmQgYHNsZWVwYCB0byBjb250aW51ZSBwcmFjdGljZSB0aGlzIHRlc3QuCgpgYGB7ciB0ZXN0IDQxIHNsZWVwLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpzbGVlcF93aWRlIDwtIHJlc2hhcGUoc2xlZXAsIGlkdmFyID0gIklEIiwgdGltZXZhciA9ICJncm91cCIsIGRpcmVjdGlvbiA9ICJ3aWRlIiwgc2VwID0gIl8iKQpzbGVlcF9tYXRyaXggPC0gYXMubWF0cml4KHNsZWVwX3dpZGVbLGMoJ2V4dHJhXzEnLCAnZXh0cmFfMicpXSkKCmxtX3NsZWVwIDwtIGxtKHNsZWVwX21hdHJpeCB+IDEpCm1hdWNobHkudGVzdChsbV9zbGVlcCwgWCA9IH4xKQpgYGAKCmBgYHtyIHRlc3QgNDEgQ2hpY2tXZWlnaHQsIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1GQUxTRX0KY2hpY2tfc3Vic2V0IDwtIENoaWNrV2VpZ2h0W0NoaWNrV2VpZ2h0JFRpbWUgJWluJSBjKDAsMiw0LDYpLF0KY2hpY2tfc3Vic2V0IDwtIGNoaWNrX3N1YnNldFtjaGlja19zdWJzZXQkQ2hpY2sgJWluJSAxOjEwLF0KCmNoaWNrX3dpZGUgPC0gcmVzaGFwZShjaGlja19zdWJzZXQsIGlkdmFyID0gIkNoaWNrIiwgdGltZXZhciA9ICJUaW1lIiwgZGlyZWN0aW9uID0gIndpZGUiLCBzZXAgPSAiXyIpCmNoaWNrX21hdHJpeCA8LSBhcy5tYXRyaXgoY2hpY2tfd2lkZVssYygid2VpZ2h0XzAiLCAid2VpZ2h0XzIiLCAid2VpZ2h0XzQiLCAid2VpZ2h0XzYiKV0pCmNoaWNrX21hdHJpeCA8LSBuYS5vbWl0KGNoaWNrX21hdHJpeCkKCmxtX2NoaWNrIDwtIGxtKGNoaWNrX21hdHJpeCB+IDEpCm1hdWNobHkudGVzdChsbV9jaGljaywgWD0gfjEpCmBgYAoKQWNjb3JkaW5nIHRvIHRoZSByZXN1bHRzLCB3ZSBjYW4gZmluZCB0aGF0IHRoZSBwLXZhbHVlIGluIHByYWN0aWNlIDEgaXMgMSBhbmQgdGhlIHAtdmFsdWUgaW4gcHJhY3RpY2UgMiBpcyAwLjQ0MzkuIEJvdGggb2YgdGhlbSBhcmUgbGFyZ2VyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlIDAuMDUuIEZvciB0aGUgcHJhY3RpY2UgMSwgdGhlcmUgYXJlIG9ubHkgdHdvIGNvbmRpdGlvbnMgaW4gdGhlIHRlc3Qgc28gdGhlcmUgaXMgbm8gdmFyaWFuY2VzIHRvIGNvbXBhcmUuIEZvciB0aGUgcHJhY3RpY2UgMiwgd2UgY2FuIG5vdCByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZSB2YXJpYW5jZXMgb2YgY29tcGFyaXNvbiBncm91cHMgYXJlIGVxdWFsLgoKIyMjIFRlc3QgNDIgQmlub21pYWwgVGVzdAoKUXVlc3Rpb24gdG8gdGhlIHRlc3QgYWRkcmVzc2VzOgoKKipEbyB0aGUgcHJvcG9ydGlvbiBvbiBvZiBpbmRpdmlkdWFscyBmYWxsaW5nIGluIGVhY2ggY2F0ZWdvcnkgZGnvrIBlciBmcm9tIGNoYW5jZT8gT3IgZG9lcyB0aGUgcHJvcG9ydGlvbiBvbiBvZiBpbmRpdmlkdWFscyBmYWxsaW5nIGludG8gZWFjaCBjYXRlZ29yeSBkaWZmZXIgZnJvbSBzb21lIHByZS1zcGVjaWZpZWQgcHJvYmFiaWxpdGllcyBvZiBmYWxsaW5nIGludG8gdGhvc2UgY2F0ZWdvcmllcz8qKgoKQSBzaW1wbGUgd2F5IHRvIHVuZGVyc3RhbmQgdGhpcyB0ZXN0IGlzIHRoYXQgaWYgd2UgZmxpcCBhIGNvaW4gMzAgdGltZXMgYW5kIGdldCAyNSBoZWFkcywgdGhpcyB0ZXN0IGNhbiB0ZWxsIHVzIHRoZSBleGFjdCBwcm9iYWJpbGl0eSBvZiB0aGF0IGhhcHBlbmluZyB3aXRoIGEgZmFpciBjb2luLgoKYGBge3IgdGVzdCA0MiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KYmlub20udGVzdCh4ID0gMjUsIG4gPSAzMCwgcCA9IDAuNSkKYGBgCgpBY2NvcmRpbmcgdG8gdGhlIHJlc3VsdCwgd2UgY2FuIGZpbmQgdGhhdCB0aGUgcC12YWx1ZSBpcyBzbWFsbGVyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlIDAuMDUuIFRoZXJlZm9yZSwgd2UgY2FuIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlIHRydWUgcHJvYmFiaWxpdHkgaXMgMC41IGZvciB0aGlzIGV4YW1wbGUuIFRoZSB0cnVlIHByb2JhYmlsaXRpZXMgYXJlIGZyb20gMC42NDUgdG8gMC45NC4KCiMjIyBUZXN0IDQzIE9uZS1TYW1wbGUgUHJvcG9ydGlvbnMgVGVzdAoKUXVlc3Rpb24gdG8gdGhlIHRlc3QgYWRkcmVzc2VzOgoKKipJcyB0aGUgb2JzZXJ2ZWQgcHJvcG9ydGlvbiBmcm9tIGEgcmFuZG9tIGV4cGVyaW1lbnQgZXF1YWwgdG8gc29tZSBwcmUtc3BlY2lmaWVkIHByb2JhYmlsaXR5PyoqCgpUaGlzIHRlc3QgaXMgc2ltaWxhciB3aXRoIEJpbm9taWFsIHRlc3QuIEl0IGlzIHN1aXRhYmxlIGZvciBsYXJnZSBzYW1wbGUgc2l6ZS4gV2UgaGF2ZSAxMDAgcGVvcGxlIGluIGEgc3VydmV5IGFuZCA1MiBvZiB0aGVtIGJlbGlldmUgdGhleSBwcmVmZXIgb3B0aW9uIEEuIFdlIGNhbiB0ZXN0IHdoZXRoZXIgdGhpcyBpcyBzaWduaWZpY2FudGx5IGZyb20gYSA1MCUgb2YgbWFya2V0IHNoYXJlLgoKYGBge3IgdGVzdCA0MywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcHJvcC50ZXN0KHggPSA1MiwgbiA9IDEwMCwgcCA9MC41KQpgYGAKCkFjY29yZGluZyB0byB0aGlzIHJlc3VsdCwgd2UgY2FuIGZpbmQgdGhhdCB0aGUgcC12YWx1ZSBpcyBsYXJnZXIgdGhhbiB0aGUgY3JpdGljYWwgdmFsdWUgMC4wNS4gVGhlcmVmb3JlLCB3ZSBjYW4gbm90IHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgb3VyIHN1cnZleSByZXN1bHQgc2hvd3MgdGhlIHNhbWUgcHJvcG9ydGlvbiBvZiBtYXJrZXQgc2hhcmUuCgojIyMgVGVzdCA0NCBPbmUtU2FtcGxlIFBvaXNzb24gVGVzdAoKUXVlc3Rpb24gdG8gdGhlIHRlc3QgYWRkcmVzc2VzOgoKKipJcyB0aGUgcmF0ZSBwYXJhbWV0ZXIgb2YgYSBQb2lzc29uIGRpc3RyaWJ1dGVkIHNhbXBsZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIGEgaHlwb3RoZXNpemVkIHZhbHVlPyoqCgpUbyB1c2UgdGhpcyB0ZXN0OgoKLSAgIGNvdW50IGRhdGEKClJlc2VhcmNoZXJzIG9ic2VydmVkICoqNiBjYXNlcyoqIG9mIGEgcGFydGljdWxhciBjYW5jZXIgaW4gYSBncm91cCBvZiByZWxhdGl2ZXMsIGJ1dCBiYXNlZCBvbiB0aGUgZ2VuZXJhbCBwb3B1bGF0aW9uLCB0aGV5IG9ubHkgKipleHBlY3RlZCA2LjIgY2FzZXMqKi4gSXMgdGhlIG9ic2VydmVkIG51bWJlciBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIHRoZSBleHBlY3RlZCBudW1iZXI/CgpgYGB7ciB0ZXN0IDQ0LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwb2lzc29uLnRlc3QoeCA9IDYsIFQgPSA2LjIpCmBgYAoKQWNjb3JkaW5nIHRvIHRoZSByZXN1bHQsIHdlIGNhbiBmaW5kIHRoYXQgdGhlIHAtdmFsdWUgaXMgbGFyZ2VyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlLiBUaGVyZWZvcmUsIHdlIGNhbiBub3QgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCB0aGUgb2JzZXJ2ZWQgbnVtYmVyIGlzIHNpZ25pZmljYW50IGRpZmZlcmVudCBmcm9tIHRoZSBleHBlY3RlZCBudW1iZXIuCgojIyMgVGVzdCA0NSBQYWlyd2lzZSBDb21wYXJpc29uIG9mIFByb3BvcnRpb25zIFRlc3QKClF1ZXN0aW9uIHRvIHRoZSB0ZXN0IGFkZHJlc3NlczoKCioqSXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgcGFpcndpc2UgcHJvcG9ydGlvbnMgaW4gdGhyZWUgb3IgbW9yZSBzYW1wbGVzIHNpZ25pZmljYW50PyoqCgpUbyB1c2UgdGhpcyB0ZXN0OgoKLSAgIHRocmVlIG9yIG1vcmUgdGhhbiB0aHJlZSBncm91cHMKClN1cHBvc2Ugd2UgaGF2ZSBkYXRhIGZyb20gc2l4IGRpZmZlcmVudCBob3NwaXRhbCB3YXJkcyBvbiB0aGUgcHJvcG9ydGlvbiBvZiBwYXRpZW50cyB3aG8gcmVjb3ZlcmVkIGFmdGVyIGEgdHJlYXRtZW50LgoKfCAgICAgIHwgICAgICAgICAgIHwgICAgICAgICAgICAgICB8CnwtLS0tLS18LS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tfAp8IFdhcmQgfCBSZWNvdmVyZWQgfCBOb3QgUmVjb3ZlcmVkIHwKfCBzMSAgIHwgOTUgICAgICAgIHwgMTA2ICAgICAgICAgICB8CnwgczIgICB8IDE4MSAgICAgICB8IDEzNyAgICAgICAgICAgfAp8IHMzICAgfCA3NiAgICAgICAgfCA4NSAgICAgICAgICAgIHwKfCBzNCAgIHwgMTMgICAgICAgIHwgMjkgICAgICAgICAgICB8CnwgczUgICB8IDExICAgICAgICB8IDI2ICAgICAgICAgICAgfAp8IHM2ICAgfCAyMDEgICAgICAgfCAxNzkgICAgICAgICAgIHwKCmBgYHtyIHRlc3QgNDUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnJlY292ZXJ5X2RhdGEgPC0gbWF0cml4KGMoOTUsIDEwNiwgMTgxLCAxMzcsIDc2LCA4NSwgMTMsIDI5LCAxMSwgMjYsIDIwMSwgMTc5KSwKICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAyLCBieXJvdyA9IFRSVUUpCgoKY29sbmFtZXMocmVjb3ZlcnlfZGF0YSkgPC0gYygiUmVjb3ZlcmVkIiwgIk5vdCBSZWNvdmVyZWQiKQpyb3duYW1lcyhyZWNvdmVyeV9kYXRhKSA8LSBjKCJzMSIsICJzMiIsICJzMyIsICJzNCIsICJzNSIsICJzNiIpCgpwYWlyd2lzZS5wcm9wLnRlc3QocmVjb3ZlcnlfZGF0YSkKYGBgCgpBY2NvcmRpbmcgdG8gdGhlIHJlc3VsdCwgd2UgY2FuIGZpbmQgdGhhdCB0aGUgcC12YWx1ZXMgYmV0d2VlbiBzMiBhbmQgczQsIHMyIGFuZCBzNSBhcmUgc21hbGxlciB0aGFuIHRoZSBjcml0aWNhbCB2YWx1ZS4gVGhlcmVmb3JlLCB3ZSBjYW4gb25seSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyBiZXR3ZWVuIHRoZXNlIHR3byBncm91cHMgdGhhdCBzMiBhbmQgczQsIHMyIGFuZCBzNSBhcmUgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQuCgojIyMgVGVzdCA0NiBUd28tU2FtcGxlIFBvaXNzb24gVGVzdAoKUXVlc3Rpb24gdG8gdGhlIHRlc3QgYWRkcmVzc2VzOgoKKipJcyB0aGUgcmF0ZSBwYXJhbWV0ZXIgb2YgYSBQb2lzc29uIGRpc3RyaWJ1dGVkIHNhbXBsZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIGFub3RoZXI/KioKClRoaXMgaXMgdGhlIHR3by1zYW1wbGUgdmVyc2lvbiBvZiB0aGUgUG9pc3NvbiB0ZXN0LgoKVG8gdXNlIHRoaXMgdGVzdDoKCi0gICB0d28gaW5kZXBlbmRlbnQgc2FtcGxlcwoKLSAgIGNvbXBhcmUgdGhlIHJhdGUgb2YgZXZlbnRzCgpXZSB3aWxsIHRlc3QgdHdvIHNhbXBsZXM6CgotICAgKipTYW1wbGUgMToqKiBPYnNlcnZlZCAxMCBldmVudHMgb3ZlciBhICJ0aW1lIGJhc2UiIG9yIGV4cG9zdXJlIG9mIDIwLDAwMCB1bml0cy4KCi0gICAqKlNhbXBsZSAyOioqIE9ic2VydmVkIDIgZXZlbnRzIG92ZXIgYSAidGltZSBiYXNlIiBvciBleHBvc3VyZSBvZiAxNyw4NzcgdW5pdHMuCgpgYGB7ciB0ZXN0IDQ2LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwb2lzc29uLnRlc3QoYygxMCwyKSxjKDIwMDAwLDE3ODc3KSkKYGBgCgpBY2NvcmRpbmcgdG8gdGhlIHJlc3VsdCwgd2UgY2FuIGZpbmQgdGhhdCB0aGUgcC12YWx1ZSBpcyBzbWFsbGVyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlLiBUaGVyZWZvcmUsIHdlIGNhbiByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZSByYXRlIG9mIHBhcmFtZXRlcnMgb2YgdGhlc2UgdHdvIHNhbXBsZXMgYXJlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50LgoKIyMjIFRlc3QgNDcgTXVsdGlwbGUgU2FtcGxlIFByb3BvcnRpb25zIFRlc3QKClF1ZXN0aW9uIHRvIHRoZSB0ZXN0IGFkZHJlc3NlczoKCioqSXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgb2JzZXJ2ZWQgcHJvcG9ydGlvbnMgZnJvbSB0d28gb3IgbW9yZSBzYW1wbGVzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gemVybz8qKgoKVG8gdXNlIHRoaXMgdGVzdDoKCi0gICB0d28gb3IgbW9yZSBpbmRlcGVuZGVudCBncm91cHMKCi0gICBjb21wYXJlIHRoZSBwcm9wb3J0aW9ucyBvZiBzdWNjZXNzZXMKCldlIHdpbGwgdXNlIHR3byBncm91cHMgdG8gcHJhY3RpY2UgdGhpcyB0ZXN0OgoKLSAgICoqR3JvdXAgMSAoTWFsZSBGYWN1bHR5KToqKiAxOCBvdXQgb2YgMzAgd2VyZSB0cmFpbmVkIGF0IHRvcC10aWVyIHNjaG9vbHMgKDE4IHN1Y2Nlc3NlcywgMzAgdHJpYWxzKS4KCi0gICAqKkdyb3VwIDIgKEZlbWFsZSBGYWN1bHR5KToqKiAxNyBvdXQgb2YgMjQgd2VyZSB0cmFpbmVkIGF0IHRvcC10aWVyIHNjaG9vbHMgKDE3IHN1Y2Nlc3NlcywgMjQgdHJpYWxzKS4KCmBgYHtyIHRlc3QgNDcsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnByb3AudGVzdChjKDE4LDE3KSxjKDMwLDI0KSkKYGBgCgpBY2NvcmRpbmcgdG8gdGhlIHJlc3VsdCwgd2UgY2FuIGZpbmQgdGhhdCB0aGUgcC12YWx1ZSBpcyBsYXJnZXIgdGhhbiB0aGUgY3JpdGljYWwgdmFsdWUuIFRoZXJlZm9yZSwgd2UgY2FuIG5vdCByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZXJlIGlzIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIHJhdGUgb2Ygc3VjY2Vzc2VzIGluIHRoZSB0d28gZ3JvdXBzLgoKIyMjIFRlc3QgNDggQ2hpLVNxdWFyZWQgVGVzdCBmb3IgTGluZWFyIFRyZW5kCgpRdWVzdGlvbiB0byB0aGUgdGVzdCBhZGRyZXNzZXM6CgoqKklzIHRoZXJlIGEgbGluZWFyIHRyZW5kIGluIHRoZSBwcm9wb3J0aW9ucyBhY3Jvc3MgbXVsdGlwbGUgb3JkZXJlZCBjYXRlZ29yaWVzPyoqCgpUbyB1c2UgdGhpcyB0ZXN0OgoKLSAgIHRocmVlIG9yIG1vcmUgb3JkZXJlZCBncm91cHMKCi0gICBmaW5kIGEgbGluZWFyIHRyZW5kIGluIHRoZSBwcm9wb3J0aW9ucyBvZiBzdWNjZXNzCgpXZSBoYXZlIHRocmVlIGdyb3VwcyB3aXRoIGluY3JlYXNpbmcgZG9zYWdlIGxldmVscy4KCi0gICAqKkdyb3VwIDEgKDEwbWcpOioqIDEwIHN1Y2Nlc3NlcyBvdXQgb2YgNTAgdHJpYWxzLgoKLSAgICoqR3JvdXAgMiAoMjBtZyk6KiogMTcgc3VjY2Vzc2VzIG91dCBvZiA1MCB0cmlhbHMuCgotICAgKipHcm91cCAzICgzMG1nKToqKiAyNSBzdWNjZXNzZXMgb3V0IG9mIDUwIHRyaWFscy4KCmBgYHtyIHRlc3QgNDgsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnN1Y2Nlc3MgPC0gYygxMCwgMTcsIDI1KQoKdG90YWxzIDwtIGMoNTAsIDUwLCA1MCkKCnByb3AudHJlbmQudGVzdChzdWNjZXNzLCB0b3RhbHMpCmBgYAoKQWNjb3JkaW5nIHRvIHRoZSByZXN1bHQsIHdlIGNhbiBmaW5kIHRoYXQgdGhlIHAtdmFsdWUgaXMgc21hbGxlciB0aGFuIHRoZSBjcml0aWNhbCB2YWx1ZS4gVGhlcmVmb3JlLCB3ZSBjYW4gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCB0aGVyZSBpcyBubyBsaW5lYXIgdHJlbmQuCgojIyMgVGVzdCA0OSBQZWFyc29uJ3MgUGFpcmVkIENoaS1TcXVhcmVkIFRlc3QKClF1ZXN0aW9uIHRvIHRoZSB0ZXN0IGFkZHJlc3NlczoKCioqQXJlIHRoZSBwYWlyZWQgb2JzZXJ2YXRpb25zIG9uIHR3byB2YXJpYWJsZXMgaW4gYSBjb250aW5nZW5jeSB0YWJsZSBpbmRlcGVuZGVudCBvZiBlYWNoIG90aGVyPyoqCgpUbyB1c2UgdGhpcyB0ZXN0OgoKLSAgIHR3byBjYXRlZ29yaWNhbCB2YXJpYWJsZXMKCldlIGhhdmUgYSBjb250aW5nZW5jeSB0YWJsZSBzaG93aW5nIHRoZSB2b3RpbmcgcGF0dGVybnMgb2YgMTAwIGNpdGl6ZW5zLCBjYXRlZ29yaXplZCBieSBnZW5kZXIgYW5kIHBvbGl0aWNhbCBwYXJ0eS4KCnwgICAgICAgIHwgICAgICAgIHwgICAgICAgICAgICAgIHwKfC0tLS0tLS0tfC0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tfAp8IEdlbmRlciB8IExhYm91ciB8IENvbnNlcnZhdGl2ZSB8CnwgTWFsZSAgIHwgMjAgICAgIHwgMzAgICAgICAgICAgIHwKfCBGZW1hbGUgfCAzMCAgICAgfCAyMCAgICAgICAgICAgfAoKV2Ugd2FudCB0byB0ZXN0IGlmIGEgcGVyc29uJ3MgZ2VuZGVyIGlzIGluZGVwZW5kZW50IG9mIHRoZWlyIGNob2ljZSBvZiBwb2xpdGljYWwgcGFydHkuCgpgYGB7ciB0ZXN0IDQ5LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQp2b3RpbmdfZGF0YSA8LSBhcy50YWJsZShyYmluZChjKDIwLCAzMCksIGMoMzAsIDIwKSkpCgpkaW1uYW1lcyh2b3RpbmdfZGF0YSkgPC0gbGlzdChnZW5kZXIgPSBjKCJNYWxlIiwgIkZlbWFsZSIpLCBwYXJ0eSA9IGMoIkxhYm91ciIsICJDb25zZXJ2YXRpdmUiKSkKY2hpc3EudGVzdCh2b3RpbmdfZGF0YSwgY29ycmVjdCA9IEZBTFNFKQpgYGAKCkFjY29yZGluZyB0byB0aGUgcmVzdWx0LCB3ZSBjYW4gZmluZCB0aGF0IHAtdmFsdWUgaXMgc21hbGxlciB0aGFuIHRoZSBjcml0aWNhbCB2YWx1ZS4gVGhlcmVmb3JlLCB3ZSBjYW4gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCB0aGUgcGVyc29uJ3MgZ2VuZGVyIGlzIGluZGVwZW5kZW50IG9mIHRoZWlyIGNob2ljZSBvZiBwYXJ0eS4KCiMjIyBUZXN0IDUwIEZpc2hlcidzIEV4YWN0IFRlc3QKClF1ZXN0aW9uIHRvIHRoZSB0ZXN0IGFkZHJlc3NlczoKCioqQXJlIHRoZSBwYWlyZWQgb2JzZXJ2YXRpb25zIG9uIHR3byB2YXJpYWJsZXMgaW4gYSBjb250aW5nZW5jeSB0YWJsZSBpbmRlcGVuZGVudCBvZiBlYWNoIG90aGVyPyoqCgpUbyB1c2UgdGhpcyB0ZXN0OgoKLSAgIHNtYWxsIHNhbXBsZSBzaXplCgotICAgdHdvIGNhdGVnb3JpY2FsIHZhcmlhYmxlcwoKV2UgaGF2ZSBhIGNvbnRpbmdlbmN5IHRhYmxlIHNob3dpbmcgdGhlIHZvdGluZyBwYXR0ZXJucyBvZiAxMDAgY2l0aXplbnMsIGNhdGVnb3JpemVkIGJ5IGdlbmRlciBhbmQgcG9saXRpY2FsIHBhcnR5LgoKfCAgICAgICAgfCAgICAgICAgfCAgICAgICAgICAgICAgfAp8LS0tLS0tLS18LS0tLS0tLS18LS0tLS0tLS0tLS0tLS18CnwgR2VuZGVyIHwgTGFib3VyIHwgQ29uc2VydmF0aXZlIHwKfCBNYWxlICAgfCAyICAgICAgfCAzICAgICAgICAgICAgfAp8IEZlbWFsZSB8IDMgICAgICB8IDIgICAgICAgICAgICB8CgpXZSB3YW50IHRvIHRlc3QgaWYgYSBwZXJzb24ncyBnZW5kZXIgaXMgaW5kZXBlbmRlbnQgb2YgdGhlaXIgY2hvaWNlIG9mIHBvbGl0aWNhbCBwYXJ0eS4KCmBgYHtyIHRlc3QgNTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnZvdGluZ19kYXRhIDwtIGFzLnRhYmxlKHJiaW5kKGMoMiwgMyksIGMoMywgMikpKQoKZGltbmFtZXModm90aW5nX2RhdGEpIDwtIGxpc3QoZ2VuZGVyID0gYygiTWFsZSIsICJGZW1hbGUiKSwgcGFydHkgPSBjKCJMYWJvdXIiLCAiQ29uc2VydmF0aXZlIikpCmZpc2hlci50ZXN0KHZvdGluZ19kYXRhKQpgYGAKCkFjY29yZGluZyB0byB0aGUgcmVzdWx0LCB3ZSBjYW4gZmluZCB0aGF0IHRoZSBwLXZhbHVlIGlzIGxhcmdlciB0aGFuIHRoZSBjcml0aWNhbCB2YWx1ZS4gVGhlcmVmb3JlLCB3ZSBjYW4gbm90IHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzLiBUaGVyZSBpcyBubyBzaWduaWZpY2FudGx5IGFzc29jaWF0aW9uIGJldHdlZW4gYSBwZXJzb24ncyBnZW5kZXIgYW5kIHRoZWlyIGNob2ljZSBvZiBwb2xpdGljYWwgcGFydHkuCgojIyMgVGVzdCA1MSBDb2NocmFuLU1hbnRlbC1IYWVuc3plbCBUZXN0CgpRdWVzdGlvbiB0byB0aGUgdGVzdCBhZGRyZXNzZXM6CgoqKklzIHRoZXJlIGEgcmVsYXRpb25zaGlwIGJldHdlZW4gdHdvIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBhZnRlciBhZGp1c3RpbmcgZm9yIGNvbnRyb2wgdmFyaWFibGVzPyoqCgpUbyB1c2UgdGhpcyB0ZXN0OgoKLSAgIE1vcmUgYWR2YW5jZWQgY2hpLXNxdWFyZWQgdGVzdAoKLSAgIHRlc3QgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIHR3byBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgYW5kIGNvbnRyb2wgZm9yIGEgdGhpcmQgY2F0ZWdvcmljYWwgdmFyaWFibGUKCldlIHdpbGwgY3JlYXRlIGEgdHJlYXRtZW50IGV4YW1wbGUgZnJvbSB0aGUgYm9vay4gV2Ugd2FudCB0byBzZWUgaWYgYSB0cmVhdG1lbnQgKCJEcnVnIiB2cy4gIlBsYWNlYm8iKSBpcyBhc3NvY2lhdGVkIHdpdGggYSByZXNwb25zZSAoIkltcHJvdmVkIiB2cy4gIk5vIENoYW5nZSIpLCB3aGlsZSBjb250cm9sbGluZyBmb3Igc2V4ICgiTWFsZSIgdnMuICJGZW1hbGUiKS4KCmBgYHtyIHRlc3QgNTEgZGF0YSBwcmVwYXJhdGlvbiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KdHJlYXRtZW50X2RhdGEgPC0gYXJyYXkoCiAgYygxMiwxNiw3LDE5LAogICAgMTYsMTEsNSwyMCksCiAgZGltID0gYygyLDIsMiksCiAgZGltbmFtZXMgPSBsaXN0KAogICAgVHJlYXRtZW50ID0gYygiRHJ1ZyIsIlBsYWNlYm8iKSwKICAgIFJlc3BvbnNlID0gYygiSW1wcm92ZWQiLCJObyBDaGFuZ2UiKSwKICAgIFNleCA9IGMoIk1hbGUiLCJGZW1hbGUiKQogICkKKQpmdGFibGUodHJlYXRtZW50X2RhdGEpCmBgYAoKYGBge3IgdGVzdCA1MSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbWFudGVsaGFlbi50ZXN0KHRyZWF0bWVudF9kYXRhKQpgYGAKCkFjY29yZGluZyB0byB0aGUgcmVzdWx0LCB3ZSBjYW4gZmluZCB0aGF0IHRoZSBwLXZhbHVlIGlzIHNtYWxsZXIgdGhhbiB0aGUgY3JpdGljYWwgdmFsdWUgMC4wNS4gVGhlcmVmb3JlLCB3ZSBjYW4gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCB0aGVyZSBpcyBubyByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdHJlYXRtZW50IGFuZCByZXNwb25zZSBldmVuIGFmdGVyIGNvbnRyb2xsaW5nIGZvciBzZXguCgojIyMgVGVzdCA1MiBNY05lbWFyJ3MgVGVzdAoKUXVlc3Rpb24gdG8gdGhlIHRlc3QgYWRkcmVzc2VzOgoKKipJcyB0aGVyZSBhIGRpZmZlcmVuY2UgYmV0d2VlbiBwYWlyZWQgcHJvcG9ydGlvbnM/KioKClRvIHVzZSB0aGlzIHRlc3Q6CgotICAgcGFpcmVkIG9yIG1hdGNoZWQgY2F0ZWdvcmljYWwgZGF0YQoKLSAgIHNhbWUgc3ViamVjdCB0d2ljZSBhbmQgdGhlIG91dGNvbWUgaXMgYmluYXJ5ICh5ZXMvbm8pCgotICAgc3VpdGFibGUgZm9yICJiZWZvcmUgYW5kIGFmdGVyIiB0ZXN0CgpGcm9tIHRoZSBib29rLCB3ZSBjcmVhdGUgYSB0YWJsZSBmb3IgdGhlIGRpYWdub3N0aWMgdGVzdHMuIFdlIGFyZSBjb21wYXJpbmcgdHdvIGRpYWdub3N0aWMgdGVzdHMgZm9yIHR1YmVyY3Vsb3NpcyAoc3B1dHVtIGN1bHR1cmUgJiBjaGVzdCByYWRpb2dyYXBoeSkgb24gdGhlIHNhbWUgZ3JvdXAgb2YgcGF0aWVudHMuCgpgYGB7ciB0ZXN0IDUyIGRhdGEgcHJlcGFyYXRpb24sIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmRpYWdub3N0aWNfZGF0YSA8LSBtYXRyaXgoCiAgYyg1OSw0LDEyOCwyMCksCiAgbnJvdyA9IDIsCiAgZGltbmFtZXMgPSBsaXN0KAogICAgIlJhZGlvZ3JhcGh5IiA9IGMoIlBvc2l0aXZlIiwiTmVnYXRpdmUiKSwKICAgICJTcHV0dW0iID0gYygiUG9zaXRpdmUiLCAiTmVnYXRpdmUiKSkKKQpmdGFibGUoZGlhZ25vc3RpY19kYXRhKQpgYGAKCmBgYHtyIHRlc3QgNTIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cm1jbmVtYXIudGVzdChkaWFnbm9zdGljX2RhdGEpCmBgYAoKQWNjb3JkaW5nIHRvIHRoZSByZXN1bHQsIHdlIGNhbiBmaW5kIHRoYXQgdGhlIHAtdmFsdWUgaXMgc21hbGxlciB0aGFuIHRoZSBjcml0aWNhbCB2YWx1ZS4gVGhlcmVmb3JlLCB3ZSBjYW4gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCB0d28gdGVzdHMgaGF2ZSB0aGUgc2FtZSBwcm9wb3J0aW9uIG9mIHBvc2l0aXZlIHJlc3VsdHMuCgojIyMgVGVzdCA1MyBFcXVhbCBNZWFucyBpbiBhIE9uZS13YXkgTGF5b3V0IChBTk9WQSkKClF1ZXN0aW9uIHRvIHRoZSB0ZXN0IGFkZHJlc3NlczoKCioqRG8gdGhyZWUgb3IgbW9yZSBzYW1wbGVzIGNvbWUgZnJvbSBwb3B1bGF0aW9ucyB3aXRoIHRoZSBzYW1lIG1lYW4/KioKClRvIHVzZSB0aGlzIHRlc3Q6CgotICAgZXh0ZW5zaW9uIG9mIHRoZSBpbmRlcGVuZGVudCB0d28tc2FtcGxlIHQtdGVzdCBbVGVzdCAxNSBUd28tc2FtcGxlIHQtdGVzdCBmb3IgdGhlIERpZmZlcmVuY2UgaW4gU2FtcGxlIE1lYW5zXQoKLSAgIHRocmVlIG9yIG1vcmUgZ3JvdXBzIG9mIHNhbXBsZXMKCi0gICBhc3N1bWUgZGF0YSB0byBiZSBub3JtYWxseSBkaXN0cmlidXRlZAoKLSAgIGFzc3VtZSB2YXJpYW5jZXMgYWNyb3NzIGRpZmZlcmVudCBncm91cHMgdG8gYmUgZXF1YWwKCldlIHdpbGwgY29tZWJhY2sgdG8gdGhlIGBjaGlja3d0c2AgZGF0YXNldCAoTGV0J3Mgc2F5ICJ0aGFuayB5b3UgY2hpY2tzISIpIGFuZCBjb21wYXJlIHRoZSBlZmZlY3RzIG9mIHNpeCBkaWZmZXJlbnQgZmVlZHMuCgpgYGB7ciB0ZXN0IDUzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpvbmV3YXkudGVzdCh3ZWlnaHQgfiBmZWVkLCBkYXRhPSBjaGlja3d0cywgdmFyLmVxdWFsID0gVFJVRSkKYGBgCgpBY2NvcmRpbmcgdG8gdGhlIHJlc3VsdCwgd2UgY2FuIGZpbmQgdGhhdCB0aGUgcC12YWx1ZSBpcyBzbWFsbGVyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlLiBUaGVyZWZvcmUsIHdlIGNhbiByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZXJlIGlzIG5vIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgaW4gdGhlIG1lYW4gd2VpZ2h0IG9mIGNoaWNrcyBhY3Jvc3Mgc2l4IGRpZmZlcmVudCBncm91cHMuCgpUaGUgQU5PVkEgdGVzdCB0ZWxscyB1cyB0aGF0IGF0IGxlYXN0IG9uZSBncm91cCBpcyBkaWZmZXJlbnQgZnJvbSBvdGhlcnMsIGJ1dCBpdCBkb2Vzbid0IHRlbGwgdXMgd2hpY2ggc3BlY2lmaWMgZ3JvdXBzIGFyZSBkaWZmZXJlbnQuIFRvIGZpbmQgdGhhdCBvdXQsIHdlIHdvdWxkIG5lZWQgdG8gcGVyZm9ybSBhIGZvbGxvdy11cCB0ZXN0LCBsaWtlIHRoZSBbVGVzdCAxNyBQYWlyd2lzZSB0LXRlc3Qgd2l0aCBDb21tb24gVmFyaWFuY2VdLgoKIyMjIFRlc3QgNTQgV2VsY2gtdGVzdCBmb3IgbW9yZSB0aGFuIHR3byBzYW1wbGVzIChXZWxjaCdzIEFOT1ZBKQoKUXVlc3Rpb24gdG8gdGhlIHRlc3QgYWRkcmVzc2VzOgoKKipEbyB5b3VyIHRocmVlIG9yIG1vcmUgc2FtcGxlcyBjb21lIGZyb20gcG9wdWxhdGlvbnMgd2l0aCB0aGUgc2FtZSBtZWFuPyoqCgpUbyB1c2UgdGhpcyB0ZXN0OgoKLSAgIGRvIG5vdCBhc3N1bWUgZXF1YWwgdmFyaWFuY2VzIGFjcm9zcyBhbGwgZ3JvdXBzCgotICAgbW9yZSByb2J1c3QgYWx0ZXJuYXRpdmUgdG8gdGhlIHN0YW5kYXJkIEFOT1ZBIHRlc3QKClRoZXJlZm9yZSwgd2Ugb25seSBuZWVkIHRvIHNldCB0aGUgYHZhci5ldXFhbCA9IEZBTFNFYC4KCmBgYHtyIHRlc3QgNTQsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cm9uZXdheS50ZXN0KHdlaWdodCB+IGZlZWQsIGRhdGE9IGNoaWNrd3RzLCB2YXIuZXF1YWwgPSBGQUxTRSkKYGBgCgpBY2NvcmRpbmcgdG8gdGhlIHJlc3VsdCwgd2UgY2FuIGZpbmQgdGhhdCB0aGUgcC12YWx1ZSBpcyBzbWFsbGVyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlLiBUaGVyZWZvcmUsIHdlIGNhbiByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4gQ29tcGFyaW5nIHdpdGggdGhlIHJlc3VsdCBmcm9tIHRlc3QgNTMsIHdlIGNhbiBmaW5kIHRoYXQgdGhlIFdlbGNoJ3MgQU5PVkEgdGVzdCBoYXMgaGlnaGVyIEYgdmFsdWUgYW5kIGxhcmdlciBwIHZhbHVlIHRoYW4gdGhlIHN0YW5kYXJkIEFOT1ZBIHRlc3QgYXMgaXQgaXMgbW9yZSByb2J1c3Qgd2l0aCBmZXdlciBjb25zdHJhaW50cy4KCiMjIyBUZXN0IDU1IEtydXNrYWwtV2FsbGlzIFJhbmsgU3VtIFRlc3QKClF1ZXN0aW9uIHRvIHRoZSB0ZXN0IGFkZHJlc3NlczoKCioqRG8geW91ciB0aHJlZSBvciBtb3JlIHNhbXBsZXMgY29tZSBmcm9tIHBvcHVsYXRpb25zIHdpdGggdGhlIHNhbWUgbWVhbj8qKgoKVG8gdXNlIHRoaXMgdGVzdDoKCi0gICBub25wYXJhbWV0cmljIGVxdWl2YWxlbnQgb2YgdGhlIG9uZS13YXkgQU5PVkEKCi0gICBjZW50cmFsIHRlbmRlbmN5IG9mIHRocmVlIG9yIG1vcmUgaW5kZXBlbmRlbnQgZ3JvdXBzCgotICAgZG8gbm90IGFzc3VtZSB0aGUgbm9ybWFsaXR5IGFzc3VtcHRpb24gb2YgQU5PVkEKCi0gICB0aGUgZXh0ZW5zaW9uIG9mIHRoZSBbVGVzdCAyNCBXaWxjb3hvbiBSYW5rIFN1bSBUZXN0IGZvciB0aGUgRGlmZmVyZW5jZSBpbiBNZWRpYW5zXQoKYGBge3IgdGVzdCA1NSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0Ka3J1c2thbC50ZXN0KHdlaWdodCB+IGZlZWQsIGRhdGEgPSBjaGlja3d0cykKYGBgCgpBY2NvcmRpbmcgdG8gdGhlIHJlc3VsdCwgd2UgY2FuIGZpbmQgdGhhdCBwLXZhbHVlIGlzIHNtYWxsZXIgdGhhbiB0aGUgY3JpdGljYWwgdmFsdWUuIFRoZXJlZm9yZSwgd2UgY2FuIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzLgoKS3J1c2thbC1XYWxsaXMgUmFuayBTdW0gdGVzdCBoYXMgZXZlbiBmZXdlciBjb25zdHJhaW50cy4gVGhlcmVmb3JlLCB0aGUgcC12YWx1ZSBpcyBsYXJnZXIgdGhhbiB0aGUgV2VsY2gncyBBTk9BLgoKIyMjIFRlc3QgNTYgRnJpZWRtYW4ncyBUZXN0CgpRdWVzdGlvbiB0byB0aGUgdGVzdCBhZGRyZXNzZXM6CgoqKkFyZSB0aGUgZGlzdHJpYnV0aW9ucyBmcm9tIHZhcmlvdXMgZ3JvdXBzIHRoZSBzYW1lIGFjcm9zcyByZXBlYXRlZCBtZWFzdXJlcz8qKgoKVG8gdXNlIHRoaXMgdGVzdDoKCi0gICByZXBlYXRlZCBtZWFzdXJlcyBvZiBBTk9WQQoKLSAgIHRocmVlIG9yIG1vcmUgcmVsYXRlZC9wYWlyZWQgZ3JvdXBzIG9mIHNhbXBsZXMKCi0gICBhc3N1bWUgZGF0YSBub3QgdG8gYmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQKCi0gICBleHRlbnNpb24gb2YgW1Rlc3QgMjAgTWF0Y2hlZCBQYWlycyBXaWxjb3hvbiBUZXN0XQoKRnJpZWRtYW4gVGVzdCBpbiBSIHJlcXVpcmVzIG1hdHJpeCBkYXRhLiBUaGVyZWZvcmUsIHdlIHdpbGwgY3JlYXRlIHRoZSBzYW1wbGUgZGF0YSBiYXNlZCBvbiB0aGUgYm9vay4KCmBgYHtyIHRlc3QgNTYgZGF0YSBwcmVwYXJhdGlvbiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZGlldF9kYXRhIDwtIG1hdHJpeChjKAogIDgsIDgsIDcsICA3LCA2LCA2LCAgNiwgOCwgNiwgIDgsIDksIDcsCiAgNSwgOCwgNSwgIDksIDcsIDcsICA3LCA3LCA3LCAgOCwgNywgNywKICA4LCA2LCA4LCAgNywgNiwgNiwgIDcsIDgsIDYsICA5LCA5LCA2CiksIG5yb3cgPSAxMiwgYnlyb3cgPSBUUlVFLApkaW1uYW1lcyA9IGxpc3QoCiAgU3ViamVjdCA9IDE6MTIsCiAgRGlldCA9IGMoIkhlYWx0aHkgQmFsYW5jZWQiLCJMb3cgRmF0IiwiTG93IENhcmIiKQopKQoKZnRhYmxlKGRpZXRfZGF0YSkKYGBgCgpgYGB7ciB0ZXN0IDU2LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpmcmllZG1hbi50ZXN0KGRpZXRfZGF0YSkKYGBgCgpBY2NvcmRpbmcgdG8gdGhlIHJlc3VsdCwgd2UgY2FuIGZpbmQgdGhhdCB0aGUgcC12YWx1ZSBpcyBzbWFsbGVyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlLiBUaGVyZWZvcmUsIHdlIGNhbiByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZXJlIGlzIG5vIGRpZmZlcmVuY2UgaW4gdGhlIHBlcmNlaXZlZCBlbmVyZ3kgbGV2ZWxzIGFjcm9zcyB0aGUgdGhyZWUgZGlldHMuCgojIyMgVGVzdCA1NyBRdWFkZSBUZXN0CgpRdWVzdGlvbiB0byB0aGUgdGVzdCBhZGRyZXNzZXM6CgoqKkFyZSB0aGUgZGlzdHJpYnV0aW9ucyBmcm9tIHZhcmlvdXMgZ3JvdXBzIHRoZSBzYW1lIGFjcm9zcyByZXBlYXRlZCBtZWFzdXJlcz8qKgoKVG8gdXNlIHRoaXMgdGVzdDoKCi0gICByZWxhdGVkIChwYWlyZWQpIHNhbXBsZXMKCi0gICBtb3JlIHBvd2VyZnVsIHRoYW4gdGhlIEZyaWVkbWFuIHRlc3QKCi0gICBzbWFsbCBudW1iZXIgb2YgZ3JvdXBzCgpgYGB7ciB0ZXN0IDU3LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpxdWFkZS50ZXN0KGRpZXRfZGF0YSkKYGBgCgpBY2NvcmRpbmcgdG8gdGhlIHJlc3VsdCwgd2UgY2FuIGZpbmQgdGhhdCB0aGUgcC12YWx1ZSBpcyBzbWFsbGVyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlLiBUaGVyZWZvcmUsIHdlIGNhbiByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZXJlIGlzIG5vIGRpZmZlcmVuY2UgaW4gdGhlIHBlcmNlaXZlZCBlbmVyZ3kgbGV2ZWxzIGFjcm9zcyB0aGUgdGhyZWUgZGlldHMuCgojIyBUZXN0aW5nIGZvciBOb3JtYWxpdHkKCiMjIyBUZXN0IDU4IEQnQWdvc3Rpbm8gVGVzdCBvZiBTa2V3bmVzcwoKUXVlc3Rpb24gdG8gdGhlIHRlc3QgYWRkcmVzc2VzOgoKKipJcyB0aGUgZGF0YSBza2V3ZWQgKHN5bW1ldHJpYyBvciBsb25nIHRhaWwgb24gb25lIHNpZGUpPyoqCgpUbyB1c2UgdGhpcyB0ZXN0OgoKLSAgIGZvciBub3JtYWxpdHkgYXNzdW1wdGlvbgoKLSAgIGxvb2tpbmcgZm9yIFNrZXduZXNzIChzeW1tZXRyaWMsIGxvbmcgdGFpbCkKCmBgYHtyIHRlc3QgNTggZGF0YSBwcmVwYXJhdGlvbiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KaWYgKCFyZXF1aXJlKCJtb21lbnRzIikpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJtb21lbnRzIikKICBsaWJyYXJ5KG1vbWVudHMpCn0KCnNldC5zZWVkKDEyMykKbm9ybWFsX2RhdGEgPC0gcm5vcm0oMTAwKQpwbG90KG5vcm1hbF9kYXRhKQpgYGAKCmBgYHtyIHRlc3QgNTgsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmFnb3N0aW5vLnRlc3Qobm9ybWFsX2RhdGEpCmBgYAoKQWNjb3JkaW5nIHRvIHRoZSByZXN1bHQsIHdlIGNhbiBmaW5kIHRoYXQgdGhlIHAtdmFsdWUgaXMgbGFyZ2VyIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlLiBUaGVyZWZvcmUsIHdlIGNhbiBub3QgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCB0aGUgZGF0YSBpcyBub3Qgc2tld2VkLgoKIyMjIFRlc3QgNTkgQW5zY29tYmUtR2x5bm4gVGVzdCBvZiBLdXJ0b3NpcwoKUXVlc3Rpb24gdG8gdGhlIHRlc3QgYWRkcmVzc2VzOgoKKipEb2VzIHRoZSBzYW1wbGUgZXhoaWJpdCBtb3JlIChvciBsZXNzKSBrdXJ0b3NpcyByZWxhdGl2ZSB0byB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbj8qKgoKKipLdXJ0b3NpczoqKiBEb2VzIHRoZSBkYXRhIGhhdmUgImhlYXZ5IiBvciAibGlnaHQiIHRhaWxzIGNvbXBhcmVkIHRvIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbj8KCkEgZGlzdHJpYnV0aW9uIHdpdGggaGlnaCBrdXJ0b3NpcyBoYXMgYSBzaGFycGVyIHBlYWsgYW5kIGhlYXZpZXIgdGFpbHMgKG1lYW5pbmcgbW9yZSBvdXRsaWVycyBhcmUgbGlrZWx5KSwgd2hpbGUgYSBkaXN0cmlidXRpb24gd2l0aCBsb3cga3VydG9zaXMgaXMgZmxhdHRlciB3aXRoIGxpZ2h0ZXIgdGFpbHMuCgpgYGB7ciB0ZXN0IDU5IGRhdGEgcHJlcGFyYXRpb24sIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmlmICghcmVxdWlyZSgibW9tZW50cyIpKSB7CiAgaW5zdGFsbC5wYWNrYWdlcygibW9tZW50cyIpCiAgbGlicmFyeShtb21lbnRzKQp9CgpzZXQuc2VlZCgxMjMpCm5vcm1hbF9kYXRhIDwtIHJub3JtKDEwMCkKcGxvdChub3JtYWxfZGF0YSkKYGBgCgpgYGB7ciB0ZXN0IDU5LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQphbnNjb21iZS50ZXN0KG5vcm1hbF9kYXRhKQpgYGAKCkFjY29yZGluZyB0byB0aGUgcmVzdWx0LCB0aGUgcC12YWx1ZSBpcyBsYXJnZXIgdGhhbiB0aGUgY3JpdGljYWwgdmFsdWUuIFRoZXJlZm9yZSwgd2UgY2FuIG5vdCByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZSBkYXRhIGhhcyB0aGUgc2FtZSBrdXJ0b3NpcyBhcyBhIG5vcm1hbCBkaXN0cmlidXRpb24uCgojIyMgVGVzdCA2MCBCb25ldHQtU2VpZXIgVGVzdCBvZiBLdXJ0b3NpcwoKUXVlc3Rpb24gdG8gdGhlIHRlc3QgYWRkcmVzc2VzOgoKKipEb2VzIHRoZSBzYW1wbGUgZXhoaWJpdCBtb3JlIChvciBsZXNzKSBrdXJ0b3NpcyByZWxhdGl2ZSB0byB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbj8qKgoKVG8gdXNlIHRoaXMgdGVzdDoKCi0gICB1c2UgR2VhcnkncyBtZWFzdXJlIHRvIG1lYXN1cmUga3VydG9zaXMKCi0gICBydW4gbXVsdGlwbGUgdGVzdHMgZm9yIHRoZSBzYW1lIHByb3BlcnR5IHRvIGltcHJvdmUgY29uZmlkZW5jZQoKTm93IHdlIHN0aWxsIHVzZSBvdXIgcHJldmlvdXMgbm9ybWFsX2RhdGEgaGVyZS4KCmBgYHtyIHRlc3QgNjAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmJvbmV0dC50ZXN0KG5vcm1hbF9kYXRhKQpgYGAKCkFjY29yZGluZyB0byB0aGUgcmVzdWx0LCB0aGUgcC12YWx1ZSBpcyBsYXJnZXIgdGhhbiB0aGUgY3JpdGljYWwgdmFsdWUuIFRoZXJlZm9yZSwgd2UgY2FuIG5vdCByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZSBkYXRhIGhhcyB0aGUgc2FtZSBrdXJ0b3NpcyBhcyBhIG5vcm1hbCBkaXN0cmlidXRpb24uCgpOb3cgbGV0J3MgdmlzdWFsaXNlIHRoZXNlIHRocmVlIHRlc3RzIGZvciB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbnMuCgpgYGB7ciB2aXN1YWxpc2F0aW9uIG9mIHRlc3QgNTggNTkgNjAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmRmX25vcm1hbF9kYXRhIDwtIGRhdGEuZnJhbWUobm9ybWFsX2RhdGEgPSBub3JtYWxfZGF0YSkKCmdncGxvdChkYXRhID0gZGZfbm9ybWFsX2RhdGEsIGFlcyh4ID0gbm9ybWFsX2RhdGEpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmRlbnNpdHkuLiksIGJpbnMgPSAxMCwgZmlsbCA9ICJza3libHVlIiwgY29sb3IgPSAiYmxhY2siKSArCiAgZ2VvbV9kZW5zaXR5KGNvbG9yID0gImJsdWUiLCBsaW5ld2lkdGggPSAxKSArCiAgc3RhdF9mdW5jdGlvbihmdW4gPSBkbm9ybSwgYXJncyA9IGxpc3QobWVhbiA9IG1lYW4obm9ybWFsX2RhdGEpLCBzZCA9IHNkKG5vcm1hbF9kYXRhKSksIGNvbG9yID0gInJlZCIsIGxpbmV3aWR0aCA9IDEsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBsYWJzKHRpdGxlID0gIkhpc3RvZ3JhbSB3aXRoIE5vcm1hbCBDdXJ2ZSBPdmVybGF5IiwKICAgICAgIHggPSAiVmFsdWUiLCB5ID0gIkRlbnNpdHkiKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKYGBge3IgUS1RIHBsb3QsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmdncGxvdChkZl9ub3JtYWxfZGF0YSwgYWVzKHNhbXBsZSA9IG5vcm1hbF9kYXRhKSkgKwogIHN0YXRfcXEoKSArCiAgc3RhdF9xcV9saW5lKGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBsYWJzKHRpdGxlID0gIlEtUSBQbG90IGZvciBOb3JtYWxpdHkiLAogICAgICAgeCA9ICJUaGVvcmV0aWNhbCBRdWFudGlsZXMiLCB5ID0gIlNhbXBsZSBRdWFudGlsZXMiKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAo=